当前位置: 首页 > 后端技术 > Node.js

【Node】常用基础API整理

时间:2023-04-03 18:38:57 Node.js

1.Debug调试方法Node的调试方法有很多种,主要分为安装node-inspect包调试、使用ChromeDevTools调试和IDE调试。安装方法可以在官网Docs调试指南中查看。下面介绍如何使用ChromeDevTools进行调试。首先,安装ChromeExtensionNIM,打开Inspect入口页面chrome://inspect,写一个简单的debug.js测试文件://apiTest/debug.jsconsole.log("thisisdebugtest")functiontest(){console.log("helloworld")}test()使用node--inspect-brk启动脚本,-brk相当于在程序入口前加了一个断点,这样程序会在执行前停止下来$node--inspect-brkapiTest/debug.jsDebuggerlisteningonws://127.0.0.1:9229/44b5d11e-3261-4090-a18c-2d811486fd0a帮助参见:https://nodejs.org/en/docs/inspector设置在chrome://inspect中监听9229(默认)端口,可以看到debug页面:{console.log("helloworld")}test()});如果我们使用node--inspect启动脚本,那么整个代码直接运行到代码末尾,无法调试,但是此时Node进程还没有结束,所以可以在http://查询devtoolsFrontendUrl/127.0.0.1:9229/json/list,把这个Url复制到Chrome中调试。看到使用ChromeDevTools调试方式还是比较复杂,部分IDE支持直接断点调试,推荐使用WebStorm和VScode。2、全局变量Node中常用的全局方法有CommonJS、Buffer、process、console、timer等,这些方法可以直接使用,不需要API。如果你想要一个可以“全局”使用的属性或方法,那么就把它挂载到Node的全局对象上:global.gNum=300console.log(gNum);//300Node中的所有模块都可以使用这些全局变量,下面将介绍Node中的全局变量2.1CommonJS模块NodeCommonJS模块规范实现了模块、exports和require模块机制。Node将每个文件封装为一个模块,每个模块都有自己的作用域,调试时可以看到:(function(exports,require,module,__filename,__dirname){//somecode});模块机制中的__dirname、__filename、exports、module、require()等变量虽然看似是全局的,但实际上只存在于模块作用域中。需要注意的几点是:模块内部的模块变量代表模块本身。该模块提供require()方法将外部模块导入当前上下文。module.exports属性表示模块的外部接口。默认快捷方式exports简单使用如下:/*common_exports.js*/exports.num=100exports.obj={a:200}exports={count:300}/*common_require.js*/constmod=require('./common_exports')console.log(mod)//{num:100,obj:{a:200}}console.log(mod.count)//undefined注意上面例子中的mod.count是未定义的,这是因为exports只是对module.exports的引用,你可以给exports添加属性,但不能修改exports的指向。更深入的了解模块机制,参见【Node】前后端模块规范及模块加载原理2.2进程进程对象process包含了进程相关的属性和方法。Node的流程文档包含了很多内容,列举了几个常用的方法。Node进程启动时传递的参数都在process.arg数组中://process.jsconst{argv,execPath}=processargv.forEach((val,index)=>{console.log(`${index}:${val}`)})console.log(execPath)在执行process.js时可以传递其他参数,这些参数会保存在argv中:$nodeapiTest/process.jsone=1--inspect--version0:/usr/local/bin/node1:/Users/mobike/Documents/webProjects/testNode/apiTest/process.js2:one=13:--inspect4:--version/usr/local/bin/nodeprocess.argv第一个参数为process.execPath,即调用执行程序Node的路径,第二个参数为要执行的JS文件路径,其余为自定义参数。process.env是一个包含各种运行环境参数的对象。可以直接输出env查看所有参数信息,也可以输出某个属性:constenv=process.envconsole.log(env.PATH)///usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/Documents/webProjects/testNode/node_modules/.binconsole.log(env.SHELL)///bin/zsh常用在webpack打包过程中.env.NODE_ENV判断生产环境还是开发环境。Process.env没有属性NODE_ENV。可以在系统环境变量中配置,也可以直接在项目程序中设置process.env.NODE_ENV='dev'。process.cwd()方法返回Node.js进程当前工作目录,与Linus命令相同$pwd://process.jsconsole.log(process.cwd())///Users/Documents/webProjects/testNode$nodeprocess.js/Users/WebstormProjects/testNode$pwd/Users/WebstormProjects/testNode2.3TimersAsynchronousNode中的timer方法类似于web浏览器中的JS定时器,但内部实现是基于Node的Event环形。Node中的定时器包括setImmediate()、setTimeout()和setInterval()。Node中有一个轻量级的process.nextTick()异步方法,在当前事件队列结束时调用,而setImmediate()是在当前NodeEventLoop结束时立即执行,那么执行顺序有什么区别呢?以下示例说明了process.nextTick(fn)与setImmediate(fn)和setTimeout(fn,0)之间的区别://timer.jssetImmediate(()=>{console.log("setImmediate")});setTimeout(()=>{console.log("setTimeout0")},0);setTimeout(()=>{console.log("setTimeout100")},100);process.nextTick(()=>{console.log("nextTick")process.nextTick(()=>{console.log("nextTickinner")})});看执行结果:$nodetimer.jsnextTicknextTickinnersetTimeout0setImmediatesetTimeout100process.nextTick()的回调函数执行得最快,因为它把异步事件插入到当前执行队列的尾部,但是如果事件执行时间在process.nextTick()太长,后续的异步事件会延迟。setImmediate()执行起来最慢,因为它将事件插入到下一个事件队列的头部,不会影响当前事件队列的执行。当setTimeout(fn,0)在setImmediate()之前执行时。2.4BufferBinaryBuffer对象用于处理二进制数据流。JS不具备处理二进制的功能,但是Node中的部分代码是用C++实现的,Node中所有的Buffer性能部分都是用C++实现的,非性能部分用JS封装。Buffer实例类似于一个整型数组,元素是两位十六进制数(0到255),挂载在全局对象上时可以不需使用。最新的BufferAPI使用Buffer.alloc(length,value)创建一个长度固定的Buffer实例。该值默认填充为0。使用Buffer.from()将其他类型的数据转换成Buffer:console.log(Buffer.alloc(5))//console.log(Buffer.alloc(5,44))//console.log(Buffer.from([3,4,5]))//console.log(Buffer.from('test'))//console.log(Buffer.from('test'))//注意字符串转Buffer时,英文占一位,中文占三位而不是四个。当汉字出现乱码时,可能会认为Buffer流没有被正确读取。Buffer类提供了几个静态方法,Buffer.byteLength()计算长度,Buffer.isBuffer()校验,Buffer.concat()拼接Buffer实例:constbuf1=Buffer.from([3,4,5])constbuf2=Buffer.from('test')console.log(Buffer.byteLength('test'))//4console.log(Buffer.byteLength('test'))//6console.log(Buffer.isBuffer('test'))//falseconsole.log(Buffer.isBuffer(buf1))//trueconsole.log(Buffer.concat([buf1,buf2]))//否则,Buffer实例也有常用的属性和方法,类似于JS中的String,包括length、toString('base64')、equals()、indexOf()等。以上是Node全局变量的概述。其他API或内置模块需要引入require('xxx')才能使用。我们可以在nodejs.cn查看更详细的GlobalAPI介绍。3、基本API3.1pathpath-relatedpath是内置的处理路径相关问题的API,可以直接与require('path')一起使用。下面举例常用路径法。路径处理常用path.normalize()规范路径,path.join()拼接路径,使用path.resolve()将相对路径解析成绝对路径:constpath=require('path')console.log(path.normalize('//asd\/das'),///asd/daspath.join('user','local'),//用户/本地path.resolve('./'))///Users/Documents/webProjects/testNode/apiTest解析一个路径,可以使用path.basename()获取文件名,path.extname()获取后缀扩展名,path.dirname()获取目录名:constpath=require('path')constfilePath='webProjects/testNode/apiTest/path.js'console.log(path.basename(filePath),//path.jspath.extname(filePath)//.js路径.dirname(filePath),//webProjects/testNode/apiTest)上面解析路径的方法得到某个值,也可以使用path.parse()将路径完全解析成一个对象,path.format()反向操作:letsp=path.parse(filePath)console.log(sp)//{root:'',//dir:'webProjects/testNode/apiTest',//base:'path.js',//ext:'.js',//name:'path'}console.log(path.format(sp))//webProjects/testNode/apiTest/path.js另外还有对系统路径的操作,使用path.sep来获取路径分隔符,路径段为分隔符,POSIX为/,Windows为\,path.delimiter获取系统路径分隔符,在POSIX上是:,在Windows上是;,示例如下:console.log(filePath.split(path.sep))//['webProjects','testNode','apiTest','path.js']console.log(process.env.PATH)//系统路径配置///usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbinconsole.log(process.env.PATH.split(path.delimiter))//['/usr/local/bin','/usr/bin','/bin','/usr/sbin','/sbin']以上是Node对路径的常用操作,需要注意的是,获取路径有几种方式,获取的路径不同:__dirname,__filename:总是返回文件的绝对路径;process.cwd()或$pwd:返回执行Node命令的文件夹;path.resolve('./'):相对于Node启动文件夹。require()中,./是相对于当前文件夹;3.3事件大多数NodeAPI都是由异步事件驱动的,所有能触发事件的对象都是EventEmitter类的Instance,通过EventEmitter.on()绑定事件,再通过EventEmitter.emit()//apiTest/events触发事件。jsconstEvents=require('events')classMyEventsextendsEvents{}constevent=newMyEvents()event.on('test-event',()=>{console.log('这是一个事件')})event.emit('test-event')setInterval(()=>{event.emit('test-event')},500)执行以上代码会不断惩罚test-event事件。当然也可以传递事件参数,可以传递多个参数。修改申诉代码如下:event.on('test-event',(data,time)=>{console.log(data,time)})event.emit('test-event',[1,2,3],newDate())$nodeapiTest/events.js[1,2,3]2019-04-23T07:28:00.420Z同一个事件监听器可以绑定多个事件,在其中添加执行触发队列时的绑定顺序,可以使用EventEmitter.removeListener()删除监听器的事件:.on('多事件',fn1)event.on('多事件',fn2)setInterval(()=>{event.emit('多事件')},500)setTimeout(()=>{event.removeListener('multi-event',fn2)},600)$nodeapiTest/events.js[1,2,3]2019-04-23T07:39:11.624Zfn1fn2fn1fn1...3.4fs文件系统节点文件模块通过require('fs)使用,所有方法都有同步和异步方法。文件系统中的异步方法,第一个参数为异常保留,操作成功时参数值为null或undefined,最后一个参数为回调函数。例如读文件的fs.readFile()和写文件的fs.writeFile()如下:constfs=require('fs')fs.readFile('./apiTest/fs.js',(err,data)=>{if(err)throwerrconsole.log('readFiledone!!!')})fs.writeFile('./apiTest/fs.txt','这是测试文件',{encoding:'utf8'},(err)=>{if(err)throwerrconsole.log('writeFiledone!!!')})推荐nodejs.cn中文版DocsAPI,查看更多NodeAPI用法。接下来对Node项目搭建、网络编程、异步编程等知识点进行梳理和学习。加油吧少年~