nodejs主线程是单线程(异步)将后续逻辑写入一个函数,传入当前执行函数,当函数执行完毕,得到结果后,将执行传递给函数(回调函数)webasynchronoussetTimeoutcallbackonclickajax阻塞不能异步(阻塞是给内核用的)IO操作,读写操作,异步操作(异步可以用但不能用同步)event-driven事件驱动(发布订阅:当前队列,异步队列)node中文文档模块node自带模块化功能,一个js文件就是一个模块。(关闭)模块这不是全局的。每个文件都有局部作用域,属性不会挂在全局上。所有模块consoleprocess进程都可以使用全局变量,设置环境变量BufferbufferclearImmediate,clearInterval,clearTimeoutsetImmediate,setInterval,setTimeout在命令行中配置NODE_ENV:exportasynchronous(nextqueue,在nextqueue的底部):process。nextTick()存在于模块范围的全局变量__dirname__filenamerequire()导出模块模块化:低耦合(各自与之前的模块没有关系),高内聚(相同的代码,相同的逻辑放在一起),易于维护,防止代码冲突(命名冲突)。单例:不保证不会有冲突,导致调用时间过长。浏览器端模块化:CMDseajs附近依赖AMDrequirejs,依赖基于标准commonjs的pre-node,基于文件读写。Node本质上是模块化的。定义如何创建一个模块,一个js文件就是一个模块如何使用一个模块,require()(带缓存功能,多次引用,只执行一次)如何导出一个模块,exports.xxx=xxx(导出的是命名对象),module.exports=xxx(getwhatyouexport)npmglobalinstallation-g,只能在命令行使用,默认安装路径可以通过npmroot-g查看。nrm(切换节点源码工具)、nvm(管理节点版本工具)不会安装到全局ratio变量中,而是通过npm进行映射。nrmtest//测试连接时间nrmls//显示所有可用源nrmusesourcename//使用源码发布包名versionmainlicense包名不能和已有入口文件一致,作用是整合注册账号,如果有一个账号,就是登录npmaddUser发布npmpublishutil.promisify()util.promiseify(fs.readFile)//承诺一个函数,存储在bufferbuffer中,看起来像一个数组,存储在内存空间中。特点:不能改变大小类似数组的操作方法buffer.fill填充缓冲区中的内容buffer.toString将缓冲区转换成字符串buffer.slice截取想要的bufferbuffer.copy复制bufferbuffer.concat的拼接方法bufferbuffer.isBuffer判断是否为buffer类型slicevarbuffer=Buffer.from([1,2,3])varnewBuffer=buffer.slice(0,1)//浅拷贝,存储wrapping前的内存地址空间但不包装后copy//targetBuffer目标缓冲区,targetStrat目标开始,sourceStart源开始,sourceEnd源结束this.length//Buffer.copy()varbuf1=Buffer.from('123')varbuf2=Buffer.from('456')varbuf=缓冲区。allocUnsafe(12)buf1.copy(buf,0)buf2.copy(buf,6)concatBuffer.concat([buf1,buf2],newBuffer.length)实现连接方法Buffer._concat=(list,totalLength=0)=>{//判断是否传递长度。如果有参数,则使用该参数。如果没有参数,则需要计算。//通过长度创建一个大缓冲区Buffer.alloc(len)//回收链表将每一项复制到大缓冲区buf.copy()//如果长度过长填充或者有效长度可以被截取slice//返回一个新缓冲区if(typeoftotalLength==='undefined'){totalLength=list.reduce((prev,next)=>prev+next.length,0)}letbuffer=Buffer.alloc(totalLength)让偏移量=0list.map(buf=>{if(!Buffer.isBuffer(buf))thrownewError('notbuffer')buf.copy(buffer,offset)offset+=buf.length})returnbuffer.slice(0,offset)}十六进制转换base64转换letbuf=Buffer.from()buf.toString('base64')一个汉字是3个字节,24位把一个汉字的24位转换成4个字节,每个汉字只有6个段中的数字,不足补0。//base64原理//1.将十六进制转换位2转为禁止toString()//2.将这些值转换成十进制,在可见代码parseInt()中获取值letbuf=Buffer.from('5')//Buffer.from('5').toString('base64')//5LqUconsole.log((0xe4).toString(2))console.log((0xba).toString(2))console.log((0x94).toString(2))//111001001011101010010100//00111001000010110010101000010100console.log(parseInt('00111001',2))console.log('0111001',2))console.log('01011')01)console.log(parseInt('00101010',2))console.log(parseInt('00010100',2))//57114220//5lqUpromisepomisechainfs模块有同步和异步两种,有异步的回调和同步的返回值。同步读取:fs.readFileSync('file','utf8'),报错需要try{}catch(){}读取文件,文件必须存在。通过/无法读取内容,/代表根目录。读取的默认类型是缓冲区。异步:fs.readFile('filename','utf8',function(err,data){})异步会导致回调地狱,不方便维护。如果第一个promise中返回了一个promise实例,则当前执行的结果会传递给下一个then。letfs=require('fs')letutil=require('util')letread=util.promiseify(fs.readFile)read('filename','utf8').then((data)=>{returnread(data,'utf8')}).then((data)=>{console.log(data)}).catch(()=>{})asyncawaitawait后面只能跟promisePormise.all()Promise。resolve()//返回成功Promise.reject()//返回失败Promise.race()path.join():加入路径path.resolve():解析绝对路径流,基于事件。eventsremoveonceonemit//订阅发布letEventEmitter=require('events')let{inherits}=require('util')functionTest(){}lettest=newTest()inherits(Girl,EventEmitter)test.on('t',function(params){//订阅console.log(1,params)})test.emit('t',2)//发布test.removeAllListeners()可读可写流:边读边写,不写-时间阅读。letfs=require('fs')letrs=fs.createReadStream(filename)//创建一个可读流并返回rs对象。您需要监听事件并等待数据到达rs.emit()。//默认数据的事情是不断触发,直到读出文件中的所有数据rs.on('data',(chunk)=>{//默认非流动模式console.log(chunk)//Bufferrs.pause();//暂停读取,暂停on('data')rs.resume();//恢复读取})//执行rs.on('end',()=当所有数据读取完毕>{})//读取错误执行rs.on('err',(err)=>{})可写流:ws.write(),ws.end()写入数据的可写流必须是String类型或Buffertypeletfs=require('fs')letws=fs.createReadStream('a.js');//可写流:ws.write()ws.end()ws.write('1')//返回是否有写入空间的布尔值ws.end('end')//调用end()后,write()不能再使用ws.on('drain',function(){//全部写入后,继续读console.log('drain')})pipe#!/usr/bin/bashletfs=require('fs')//30B读4B5次,读第一次开始写,只写1B,暂停读取,drain后恢复读取functionpipe(source,target){letrs=fs.createReadStream(source,{highWaterMark:4})letws=fs.createWriteStream(target,{highWaterMark:1})//打开可读流rs.on('data',function(chunk){if(ws.write(chunk)===false){//可写流不能再写入rs.pause()//暂停读取}})letcount=1ws.on('排水管',function(){console.log(count)count+=1rs.resume()//继续读取})//全部读取完成后关闭写入rs.on('end',()=>{ws.end()})//可以直接使用pipe()//rs.pipe(ws)//可读stream.pipe(可写流),会自动调用write和end方法}pipe('a.txt','b.txt')httpserverlethttp=require('http')letfs=require('fs')http.createServer((req,res)=>{//req表示客户端是可读流//res表示服务end是可写流fs.createReadStream('index.html').pipe(res)}).listen(3000)基于promifetch(url,{method:'GET'}).then((res)=>{console.log(res.text())returnres.text()}).then((data)=>{console.log(data)}).catch(err=>{console.log(err)})