Node基础

65 阅读6分钟

node.js

API文档: nodejs.cn/api/

global

global是node.js的全局对象,相当于ECMA Script中的windows,其方法和属性都是全局成员

__filename 返回当前js文件名称

__dirname 返回当前js文件路径(不包含文件名)

process.argv

返回一个数组,第0项为node环境文件全路径,第1项为当前模块文件全路径,第2项之后都是访问node.js模块文件时传入的参数

Buffer

缓存器(处理字节数组)

构造方法(类)

  1. Buffer.alloc/allocUnsafe(size) 初始化/未初始化实例
  2. Buffer.from(string/array/object/buffer,offset/length/encoding) 返回buffer

静态方法

  1. Buffer.isEncoding("utf8") 判断参数编码是否被支持
  2. Buffer.isBuffer(buf) 判是否为Buffer字节序列
  3. Buffer.byteLength(buf) 返回参数Buffer实例的字节长度
  4. Buffer.concat(bufferArray/Array) 拼接多个Buffer实例后返回这个新实例

实例方法

  1. buf.write("page",1,3) 重写Buffer实例的字节序列,默认从索引0字节开始,这里从字节索引为1向后写入3长度个"page"内容
  2. buf.slice(1,3) 自索引1截至索引3之前的Buffer字节序列并返回
  3. buf.toString() 将Buffer实例转为其编码格式的字符串并返回
  4. buf.toJson() 该方法不需显式调用,通过JSON.stringify(buf)自动调用,将Buffer实例转为json串:'type:"Buffer",data:[...]'

模块

解决问题

命名冲突

文件依赖:各个模块文件之间依赖,新的模块文件需引入太多依赖文件

模块规则

模块定义 1个js文件对应1个模块,模块之间相互独立

模块使用 module.require("url") 当前模块内引入依赖模块 module.exports 被依赖模块文件向外导出内部引用

通过module.exports.fn = ... 来向外导出module的方法/属性; 但是另外提供了快捷方式exports.fn = ...,效果同上;

//直接添加至引用导出对象
module.exports.hello = func;
exports.hello = func;(快捷方式)
// 重写了引用导出对象( module.exports),导出无效
exports = {
   sum:sum
};
//但是以下写法重写快捷方式(exports),但未重写module.exports
module.exports = {//批量导出
   sum:sum
};
//重写module.export,此时只能导出1个方法/属性,外部引入后直接使用
module.exports = sum;

模块识别 node.js仅识别js,json,node格式文件为模块,未写后缀名下按此顺序查找

模块缓存 重复引用相同路径的模块不会多次执行模块内部,因为node会缓存已引用模块

模块分类 系统模块,自定义模块,第三方模块

传统库模块化

// 以QRCode(文本转二维码)为例
(function(root, factory) {
  // 判断模块化对象
  if (typeof define === "function" && define.amd) { // 支持AMD
    define("QRCode", factory);
  } else if (typeof module === "object" || typeof exports === "object") { // 支持CommonJS
    module.exports = factory();
    // QRCode = factory();
  } else {  // js全局
    root.QRCode = factory();
  }
})(this,function() {
  // ...qrcode核心方法
})

核心模块

path

路径模块(path字符串处理)

  • .basename(pathStr,".html") 获取path串最后一部分(文件夹/文件名称),第2参会去掉path串尾部文件后缀并返回
  • .dirname(pathStr) 返回path串的路径部分(除去了最后一部分)
  • .extname(pathStr) 返回path串目标文件扩展名(.文件后缀),文件夹则返回(.文件夹名)
  • .parse(pathStr) 将path串转为指定属性的对象并返回:root,dir,base,ext,name,5个属性
  • .format(obj) 将指定path属性的对象转为path串并返回
  • .isAbsolute("str") 判断是否为根路径,window以冒号识别"C:/",Linux以反斜杠识别"/foo/index"
  • .join("user/index","..","user.html") 将多个路径智能合成1个正确path串,能够自动识别".",".."进行路径跳转
  • .normalize(pathStr) 将path串规范化为正确的路径并返回
  • .relative(pathStr1,pathStr2) 计算出基于参数1路径转至参数2路径的相对路径串并返回
  • .resolve(pathStr1,pathStr2) 基于当前执行路径计算路径参数们后返回绝对路径串,若路径参数带有根路径则基于此根路径
  • .delimiter/.sep() 分别返回当前系统平台的环境变量分隔符(;或:)和路径分界符(/或);

nodejs的异步I/O(磁盘->内存->磁盘)思想

  1. nodejs异步的执行任务
    • 文件操作
    • 网络操作
  2. nodejs异步事件模型 单线程 + 事件队列
  3. nodejs异步处理 同步处理直接调用方法,接受返回值后进行操作 异步处理通过回调函数进行处理(回调函数参数一般包括error参数和返回值参)

flie

文件模块(文件操作)

  • .stat(filePath,(error,stat) => {}) 获取文件信息 参数1为文件路径; 参数2为回调函数,其中error为错误对象,默认为null;stat为文件对象; stat对象的相关属性:birthtime(文件创建时间),atime(访问时间),mtime(数据被修改时间),ctime(文件状态信息修改时间)

  • .readFile(filePath,encoding,(error,data) => {}) 读取文件内容 data参为文件内容返回值,默认以Buffer字节序列返回; 若指定了encoding参数则将data进行字符编码后返回;

  • .writeFile(filePath,data,encoding,(error) => {}) data为写入数据,可以为字符串,Buffer;encoding默认为"utf8" 该方法写入会覆盖原文件内容,若原文件不存在则创建后写入

  • .existsSync(filePath)

    指定路径是否存在目标文件

  • 流式操作(适用大文件操作)

    • .createReadyStream(path,options..) 事件:data,end... 方法:pipe

    • .createWriteStream(path,options..) 方法:write

      let readstream = file.createReadStream(rpath); //从文件创建流
      let writestream = file.createWriteStream(tpath); //创建写入流
      let num = 0;
      // nodejs基于事件的处理方式提供处理方法
      readstream.on("data",(chunk) => { //监听读取data期间的一波波chunk(流)
        writestream.write(chunk); //处理:一波波流接后写入
        num++;
      });
      readstream.on("end",() => {
        console.log(num);
      });
      //快捷方式
      readstream.pipe(writestream); // 文件流导入
      
    • .mkdir(pathStr,(err) => {}) 创建目录 根据pathStr创建路径的尾部目录

    • .readdir(pathStr,(error,files)=>{}) 读取目录 读取指定路径的目录,并返回一个数组格式的目录项列表files

    • .rmdir(pathStr,(error) => {}) 删除路径尾部目录

http

模块(用于服务端处理http服务)

  • http.createServer((req,res) => {...}) 创建并开启一个http服务类对象并返回,其callback为该对象的request事件的处理

  • server.listen("端口号",IP地址,() => {...}) 设置一个server服务监听的端口,ip地址可选,其callback为监听成功后处理

  • http.incomingMessage类 request对象为该类实例,方法/属性:write,url(仅包含路径部分),method

  • http.ServerResponse类 response对象为该类实例,方法/属性:write,end,writeHead

  • http.request(options,(res) => {...}) 从当前服务器向指定地址发送请求并返回请求一个res对象,options为请求参数对象;

url

模块(处理/解析url串)

  • .parse("url串",boolean) 将url串转为特定属性对象并返回,第2参为是否将query串对象返回 特定对象属性包括protocal,hostname,path,pathname,query,hash,

  • .format(obj) 将具有特定属性与url值的对象转为url串并返回

  • querystring模块(post参数)

  • .parse("查询参数串") 将post参数(具有%格式)转义后返回参数对象,与url.parse("url串").query类似 若参数的键存在重复,则生成将值合成为数组

  • .stringfy(obj) 将一个参数对象转为post查询参数串并返回

实现

静态资源托管

let path = require("path");
let fs = require("fs");
let url = require("url");

let mime = require("./mime.json"); //文件类型与mime信息映射

let serverStatic = (request,response,root=".") => {
    let urlObject = url.parse(request.url,true);
    let pathName = urlObject.pathname;
    fs.readFile(root+pathName,"utf8",(error,fileContent) => {
        if(error) response.writeHead(404,{"content-type":"text/plain;charset:utf-8;"});
        let extname = path.extname(pathName);
        let mimeType = "text/html";
        if(mime[extname]){
            mimeType = mime[extname]
        };
        if(mimeType.startsWith("text")){
            mimeType += ";charset:utf-8;"
        }
        response.writeHead(200,{"content-type":mimeType});
        response.end(fileContent);
    })
};
exports.serverStatic = serverStatic;