NodeJs基础

193 阅读5分钟

Nodejs相关框架:

express // ES5写法

koa // 支持ES6

egg // 企业级框架

CommonJs规范

1. commonjs是一种规范 因为js没有模块的功能所以CommonJS应运而生,它希望js可以在任何地方运行,不只是浏览器中

2. NodeJS是commonjs规范的实现

3. Node模块采用了CommonJS规范,一个单独的文件就是一个模块。每一个模块都是一个单独的作用域,也就是说,在一个文件定义的变量(还包括函数和类),都是私有的,对其他文件是不可见的。

4. 所有变量都包在匿名函数里,所以不会污染全局变量

require命令

1. require命令是CommonJS规范之中,用来加载其他模块的命令

2. require命令的基本功能是,读入并执行一个JavaScript文件,然后返回该模块的module.exports对象。
   如果没有发现指定模块,会报错 ; 
   如果指定的模块文件没有发现,Node会尝试为文件名添加.js、.json、.node后缀,再去搜索

3. 根据参数的不同格式,require命令去不同路径寻找模块文件。
   如果参数字符串以“/”开头,则表示加载的是一个位于绝对路径的模块文件
   如果参数字符串以“./”开头,则表示加载的是一个位于相对路径

module

1. 每个模块内部,都有一个module对象,代表当前模块

2. Node内部提供一个Module构建函数。所有模块都是Module的实例

3. module属性:
    module.id 模块的识别符,常是带有绝对路径的模块文件名。
    module.filename 模块的文件名,带有绝对路径。
    module.loaded 返回一个布尔值,表示模块是否已经完成加载。
    module.parent 返回一个对象 / null,表示调用该模块的模块。
    module.children 返回一个数组,表示该模块要用到的其他模块。
    module.exports 表示模块对外输出的值。

4. CommonJS规定,每个文件的对外接口是module.exports对象。
   这个对象的所有属性和方法,都可以被其他文件导入。
   当调用require方法引入模块时,其实是加载该模块的module.exports属性

5. module.exports 初始值为一个空对象 {}。

exports

为了方便,Node为每个模块提供一个exports变量,指向module.exports

module.exports 和 exports 区别

module.exports抛出当前内容形式,exports抛出对象

1. 当调用require方法引入模块时,实则引入的是当前模块的module.exports属性值。

2. Node为每个模块提供一个exports变量,指向module.exports,如果直接给exports赋值,相当于切断了它与module.exports的联系
   此时exports变量将不再指向module.exports属性。所以只能采用向exports变量中追加键值对的方式将其抛出

清除模块缓存

Object.keys(require.cache).forEach(function (file) {
  delete require.cache[file];
});

commomjs特点

1. 所有代码都运行在模块作用域,不会污染全局作用域。

2. 模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果 require.cache

3. 模块加载的顺序,按照其在代码中出现的顺序

基础服务的搭建

<!-- 引入内置模块http -->
var http=require('http');

<!-- 引入内置模块path -->
var path=require('path');

<!-- 引入内置模块fs -->
var fs=require('fs');

var MIME={
  '.html':'text/html;charset=utf-8',
  '.css':'text/css'
}

<!-- 创建服务 -->
var server=http.createServer(function(req,res){

  <!-- 跳过favicon请求 -->
  if(req.url==='/favicon.ico'){
    return;
  }

  <!-- 获取文件后缀名 -->
  var ext=path.extname(req.url);

  <!-- 设置响应头信息 -->
  res.writeHead(200,{'content-type':MIME[ext] || 'text/html'})

  <!-- 拼接完整路径 -->
  var pathname='';
  if(req.url==='/'){
    pathname=path.resolve('www','index.html');
  }else{
    pathname=path.join(__dirname,'www',req.url);
  }

  <!-- 读取抛出文件 -->
  fs.readFile(pathname,function(err,data){
    if(err){
      throw err
    }
    res.end(data)
  })

  <!-- 设置响应内容 -->
  // res.write('hello word')

  <!-- 结束响应 -->
  // res.end();
})

<!-- 监听端口号 -->
server.listen(8888,function(){

  <!-- 打印服务器地址信息 -->
  console.log(server.address())
})

错误捕获写法

<!-- 此代码在createServer内部 -->

try{
  res.writeHead(200,{'Content-Type':MIME[ext]});
  res.end(fs.readFileSync(pathname));
}catch(e){
  res.writeHead(404);
  res.end('not found!');
}

POST请求监听

<!-- 此代码在createServer内部 -->

var str='';
req.on('data',function(chunk){
  str+=chunk
})
req.on('end',function(){
  console.log(str);
})
res.end('hello');

querystring 库的使用

var querystring=require('querystring');
var str='a=1&b=2&c=3';
var obj={a:1,b:2,c:3};
var demo='你好朋友'; 

// 转对象
console.log(querystring.parse(str))

// 转字符串
console.log(querystring.stringify(obj))

// 编码
console.log(querystring.escape(demo)) 

// 解码
console.log(querystring.unescape(querystring.unescape(demo)))

设置支持跨域访问

res.writeHead(200,{
  'access-control-allow-origin':'*'
})

cheerio库(第三方爬虫包)

var cheerio=require('cheerio');
http.get('http://www.baidu.com',function(res){
  var str='';
  res.on('data',function(chunk){
    str+=chunk
  })
  res.on('end',function(){
    var $=cheerio.load(str);

    <!-- 查找<ul>标签下<a>标签的text文本 -->
    console.log($('#ul > a').text());
  })
})

zlib

var zlib=require('zlib');
var fs=require('fs');

// 创建一个只读数据流
var rs=fs.createReadStream('./css.js');

// 创建一个压缩流
var gzip=zlib.createGzip();

// 创建一个只写数据流
var ws=fs.createWriteStream('./newcss.js');
rs.pipe(gzip).pipe(ws);

express极简框架

var express=require('express');
const { url } = require('inspector')

// 创建app应用
var app=express();

// 注册路由
app.all('/',function(req,res){
  res.end('all');
})
app.get('/',function(req,res){
  res.end('get');
})
app.post('/',function(req,res){
  res.end('post');
})

// 监听端口
app.listen(8888);

NodeJs的响应方式

res.download()  // 提示下载文件

res.end()  // 终结响应处理流程

res.json()  // 发送一个json格式的响应

res.jsonp()  // 发送一个支持jsonp的json格式响应

res.redirect()  // 重定向请求

res.render()  // 渲染视图模板

res.send()  // 发送各种类型的响应

res.sendFile()  // 以八位字节流的形式发送文件

res.sendStatus()  // 设置响应状态码,并将其以字符串形式作为响应体的一部分发送

NodeJs线上管理工具(pm2)

pm2 list: // 查看服务列表

pm2 stop ${id}: // 停止服务

pm2 start ${id}: // 启动服务

pm2 restart ${id}: // 重启服务

pm2 log: // 服务日志

常用NodeJs的内置模块和API

<!-- http模块 : 实现网络相关 -->

<!-- path模块 : 用于处理文件和目录的路径 -->

  path.dirname(path)  // 返回 path 的目录名

  path.extname(path)  // 返回 path 的扩展名

  path.isAbsolute(path) // 检测 path 是否为绝对路径

  path.join([...paths]) // 拼接合并path

  path.parse(path)  // 返回一个path对象,包含有效属性

  path.relative(from, to) // 返回 from 到 to 的相对路径

  path.resolve([...paths]) // 将路径或路径片段的序列解析为绝对路径

<!-- fs模块 : 读取操作文件 -->

  fs.appendFile(path, data[, options], callback)  // 异步地追加数据到文件,如果文件尚不存在则创建文件

  fs.chmod(path, mode, callback)  // 异步地更改文件的权限

  fs.copyFile(src, dest[, mode], callback)  // 异步地将 src 拷贝到 dest

  fs.open(path[, flags[, mode]], callback)  // 异步地打开文件

  fs.opendir(path[, options], callback) // 异步地打开目录

  fs.mkdir(path[, options], callback) // 异步地创建目录

  fs.readFile(path[, options], callback)  // 异步地读取文件的全部内容

  fs.writeFile(file, data[, options], callback) // 异步地写入数据到文件

<!-- url模块 : 用于处理与解析 URL -->
  
  url.href:'http://xiaoningzi:123@github.com:80/2020jsnode?name=xnz&age=25#top'  // 完整的地址

  url.protocol:'http'  // http/https协议

  url.slashes:true  // 是否有// 

  url.auth:'xiaoningzi:123' // 用户名和密码

  url.host:'github.com:80' // 主机

  url.port:'80' // 端口

  url.hostname:'github.com' // 域名

  url.hash:'#top' // 片段标示符,指向HTML页面某个DOM元素的ID

  url.search:'?name=xnz&age=25'  // ?+查询字符串

  url.query:'name=xnz&age=25'  // 查询字符串

  url.pathname:'/2020jsnode'  // 端口号和?中间的那部分

  url.path:'/2020jsnode?name=xnz&age=25' // pathname+search

<!-- querystring模块 : 用于解析和格式化 URL 查询字符串的实用工具 -->
  
  querystring.parse(str[, sep[, eq[, options]]])  // 查询字符串转对象

  querystring.stringify(obj[, sep[, eq[, options]]])  // 对象转字符串

  querystring.escape(str) // 编码

  querystring.unescape(str) // 解码