node.js
API文档: http://nodejs.cn/api/
global
global是node.js的全局对象,相当于ECMA Script中的windows,其方法和属性都是全局成员
__filename 返回当前执行js脚本名称
__dirname 返回当前执行js脚本路径(不包含文件名)
process
process.argv
返回一个数组,第0项为node环境文件全路径,第1项为当前模块文件全路径,第2项之后都是访问node.js模块文件时传入的参数
process.cwd()
获取当前工作目录的绝对路径,即运行终端基于的目录
process.env
获取当前执行环境的环境变量(对象),如 NODE_ENV=production node index.js
process.exit([code])
终止 Node.js 进程,便输出 code
自定义状态信息
Buffer
缓存器(处理字节数组)
构造方法(类)
Buffer.alloc/allocUnsafe(size)
初始化/未初始化实例Buffer.from(string/array/object/buffer,offset/length/encoding)
返回buffer
静态方法
Buffer.isEncoding("utf8")
判断参数编码是否被支持Buffer.isBuffer(buf)
判是否为Buffer字节序列Buffer.byteLength(buf)
返回参数Buffer实例的字节长度Buffer.concat(bufferArray/Array)
拼接多个Buffer实例后返回这个新实例
实例方法
buf.write("page",1,3)
重写Buffer实例的字节序列,默认从索引0字节开始,这里从字节索引为1向后写入3长度个”page”内容buf.slice(1,3)
自索引1截至索引3之前的Buffer字节序列并返回buf.toString()
将Buffer实例转为其编码格式的字符串并返回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(磁盘->内存->磁盘)思想
- nodejs异步的执行任务
- 文件操作
- 网络操作
- nodejs异步事件模型 单线程 + 事件队列
- 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..)
方法:writelet 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查询参数串并返回
util
util.inspect(obj, { depth: num })
对象转字符串,可用于良好的打印输出
util.format(format, …args)
格式化字符串
util.callbackify
promise转回调函数
const callbackFoo = util.callbackify(foo);
callbackFoo((err, ret) => {
if (err) {
console.log('err', err)
return
}
console.log(ret)
})
其中 foo 为返回 promise 的方法
util.promisify
回调函数转promise
try{
await util.promisify(fs.readFile)
}catch(e){
console.log(e)
}
child_process
用于创建子进程也能实现多任务并行处理,也可通过其调用系统的功能指令完成复杂的任务
spawn
启动一个子进程来执行指定的命令,并且可以通过流式数据通信与子进程进行交互;
import ChildProcess from 'child_process'
const { spawn, spawnSync } = ChildProcess
const file = './../fs/index.mjs'
const spawnProcess = spawn('git', ['log', '-1', '--pretty="%ci"', file])
spawnProcess.stdout.on('data', (data) => {
console.log(`stdout: ${data}`)
console.log(new Date(data))
})
exec
启动一个 shell,并在 shell 中执行指定命令,执行完毕后插入 stdout/stderr
中,适用于一些命令行工具;
import { exec, execSync } from 'child_process'
const pwd = execSync('pwd')
console.log(pwd.toString())
const ls = execSync('ls -lh')
console.log(ls.toString())
execFile
直接执行某个文件,而无需通过 shell 执行
import { execFile, execFileSync } from 'child_process'
const file = './hello'
const execData = execFileSync(file)
console.log(execData.toString())
fork
衍生新的进程来执行 JavaScript 文件,并且建立一个与子进程的 IPC 通信管道。
import { fork } from 'child_process'
const child = fork('child.mjs') // 使用 fork() 方法创建子进程
child.on('message', (msg) => {
// 监听来自子进程的消息
console.log(`Message from child: ${msg}`)
})
child.send('Hello from parent!') // 向子进程发送消息
EventLoop
事件循环
微任务:nextTick、promise
宏任务:setTImeout
I/O队列回调:readFile
setImmediate回调
关闭事件队列回调:process.on(‘exit’)
调试
VS Code调试
VS Code 侧边栏【运行和调试】里,【JavaScript调试终端】按钮新建调试终端,输入运行命令进入调试
或在 package.json
下 scripts
配置处【调试】快捷运行调试终端命令,点击进入调试
实现
静态资源托管
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;