当前位置: 首页 > 科技观察

NodeJS文档中读到的19个例程

时间:2023-03-13 23:49:19 科技观察

虽然我用了三年多的NodeJS,但我曾经自以为无所不知。但我似乎从来没有安静的时间坐下来仔细阅读NodeJS的完整文档。熟悉我的朋友应该知道,我之前看过HTML、DOM、WebAPIs、CSS、SVG和ECMAScript的文档,而NodeJS是这个系列最后要读的一座山。在阅读文档的过程中,我也发现了很多以前不知道的知识,觉得有必要分享给大家。不过文档比较直白,所以我也按照阅读顺序列出了我认为需要理解的点。querystring:一个可以用作通用解析器的模块。很多时候我们会从数据库或其他地方得到这种奇怪格式的字符串:name:Sophie;shape:fox;condition:new。一般来说,我们会使用字符串切割的方法,将字符串分割成JavaScript对象。但是querystring也是一个很好的现成工具:constweirdoString=`name:Sophie;shape:fox;condition:new`;constresult=querystring.parse(weirdoString,`;`,`:`);//result://{//name:`Sophie`,//shape:`fox`,//condition:`new`,//};V8Inspector使用--inspect参数运行您的Node应用程序,它会给您一个特定的URL。将此URL复制到Chrome中并打开它,您可以使用ChromeDevTools来调试您的Node应用程序。详细实验可以参考这篇文章。但是请注意,此参数仍处于试验阶段。nextTick和setImmediate的区别这两个产品从名字上可能看不出区别,我觉得应该起个别名:process.nextTick()应该是process.sendThisToTheStartOfTheQueue()setImmediate应该是sendThisToTheEndOfTheQueue()说不相关,React中的Props应该是stuffThatShouldStayTheSameIfTheUserRefreshes,State应该是stuffThatShouldBeForgottenIfTheUserRefreshes。Server.listen可以使用Object作为参数。我更喜欢调用带命名参数的函数,这比只遵循顺序的无名参数方法更直观。不要忘记Server.listen也可以使用对象作为参数:require(`http`).createServer().listen({port:8080,host:`localhost`,}).on(`request`,(req,res)=>{res.end(`HelloWorld!`);});但是,这个特性并没有在http.ServerAPI中表达,而是在其父net.Server的文档中。相对地址你传给fs模块的距离可以是相对地址,也就是相对于process.cwd()。估计早就有人知道了,但一直以为只能用绝对地址:constfs=require(`fs`);constpath=require(`path`);//whyhaveIalwaysdonethis...fs.readFile(path.join(__dirname,`myFile.txt`),(err,data)=>{//dosomething});//whenIcouldjustdothis?fs.readFile(`./path/to/myFile.txt`,(err,data)=>{//dosomething});PathParsing:路径解析之前从来不知道的一个功能就是从一个文件名中解析出路径,文件名,文件扩展名等:myFilePath=`/一些目录/一些文件。json`;path.parse(myFilePath).base===`someFile.json`;//truepath.parse(myFilePath).name===`someFile`;//truepath.parse(myFilePath).ext===`.json`;//trueLoggingwithcolors别忘了console.dir(obj,{colors:true})可以用不同的颜色打印键和值,这会大大增加日志的可读性。使用setInterval执行定时任务。我喜欢使用setInterval来执行定期的数据库清理任务。但是,默认情况下,当setInterval存在时,NodeJS不会退出。您可以使用以下方法让Node进入睡眠状态:constdailyCleanup=setInterval(()=>{cleanup();},1000*60*60*24);dailyCleanup.unref();UseSignalConstants如果您尝试终止进程在NodeJS中,估计你用过如下语法:process.kill(process.pid,`SIGTERM`);这没问题,但是由于第二个参数可以同时使用字符串和整数变量,所以最好使用全局变量:在IP地址验证工具中,它使您无需编写额外的正则表达式:require(`net`).isIP(`10.0.0.1`)返回4require(`net`).isIP(`cats`)返回0os.EOF。不知道你有没有手写行尾。它看起来不漂亮。NodeJS内置了os.EOF,在Windows下是rn,其他地方是n。使用os.EOL可以让你的代码在不同的操作系统上保持一致:constfs=require(`fs`);//badfs.readFile(`./myFile.txt`,`utf8`,(err,data)=>{data.split(`\r\n`).forEach(line=>{//dosomething});});//goodconstos=require(`os`);fs.readFile(`./myFile.txt`,`utf8`,(err,data)=>{data.split(os.EOL).forEach(line=>{//dosomething});});HTTP状态码NodeJS帮助我们构建HTTP状态码及其描述,即http.STATUS_CODES,key是状态值,value是描述:可以如下使用:someResponse.code===301;//truerequire(`http`).STATUS_CODES[someResponse.code]===`MovedPermanently`;//true避免异常崩溃有时遇到以下情况导致比较无奈服务器崩溃:constjsonData=getDataFromSomeApi();//Butohno,baddata!constdata=JSON.parse(jsonData);//响亮的噪音。为了避免这种情况,我加了一个全局的:process.on(`uncaughtException`,console.error);当然,这种方法绝不是最佳实践。如果是在大项目中,我还是会用pm2,然后把所有可能的crash代码都加到try...catch中。只是这个once()除了on方法,once方法也适用于所有EventEmitter,我希望我不是最后一个知道这个的:server.once(`request`,(req,res)=>res.end(`Nomorefromme.`));自定义控制台您可以使用newconsole.Console(standardOut,errorOut),然后设置自定义输出流。您可以选择创建一个控制台来将数据输出到文件或Socket或第三方。DNS查找一个小哥跟我说,Node不会缓存DNS查找信息,所以你在使用URL之后要等几毫秒才能拿到数据。但实际上,你可以使用dns.lookup()来缓存数据:dns.lookup(`www.myApi.com`,4,(err,address)=>{cacheThisForLater(address);});fs在不同操作系统上可用某些差异fs.stats()返回的对象中的模式属性在Windows和其他操作系统之间有所不同。fs.lchmod()仅适用于macOS。仅Windows支持使用类型参数调用fs.symlink()。在macOS和Windows上调用fs.watch()时仅传递递归选项。在Linux和Windows中,fs.watch()的回调可以传入一个文件名。使用fs.open()和a+属性打开目录时,仅在FreeBSD和Windows上有效,但在macOS和Linux上存在问题。.在Linux下以追加模式打开文件时,传递给fs.write()的位置参数将被忽略。net模块的速度几乎是http的两倍。在文档中看到了一些关于两者性能的讨论,我也跑了两台服务器进行了真实的对比。因此,http.Server每秒可以接收大约3400个请求,而net.Server可以接收大约5500个请求。//Thismakestwoconnections,onetoatcpserver,onetoanhttpserver(bothinserver.js)//Itfiresoffabunchofconnectionsandtimestheresponse//Bothsendstrings.constnet=require(`net`);consthttp=require(`http`);functionparseIncomingMessage(res){returnnewPromise((resolve)=>{letdata=``;res.on(`data`,(chunk)=>{data+=chunk;});res.on(`end`,()=>resolve(data));});}consttestLimit=5000;/*----------------*//*--NETclient--*//*-------------------*/functiontestNetClient(){constnetTest={startTime:process.hrtime(),responseCount:0,testCount:0,payloadData:{type:`millipede`,feet:100,test:0,},};functionhandleSocketConnect(){netTest.payloadData.test++;netTest.payloadData.feet++;constpayload=JSON.stringify(netTest.payloadData);this.end(payload,`utf8`);}functionhandleSocketData(){netTest.responseCount++;if(netTest.responseCount===testLimit){consthrDiff=process.hrtime(netTest.startTime);constelapsedTime=hrDiff[0]*1e3+hrDiff[1]/1e6;constrequestsPerSecond=(testLimit/(elapsedTime/1000)).toLocaleString();console.info(`net.Serverhandledanaverageof${requestsPerSecond}requestspersecond.`);}}while(netTest.testCount{httpTest.responseCount++;if(httpTest.responseCount===testLimit){consthrDiff=process.hrtime(httpTest.startTime);constelapsedTime=hrDiff[0]*1e3+hrDiff[1]/1e6;constrequestsPerSecond=(testLimit/(elapsedTime/1000)).toLocaleString();console.info(`http.Serverhandledanaverageof${requestsPerSecond}requestspersecond.`);}});}while(httpTest.testCount{console.info(`StartingtestNetClient()`);testNetClient();},50);setTimeout(()=>{console.info(`StartingtestHttpClient()`);testHttpClient();},2000);//这个setsuptwoservers.ATTCPandanHTTPone.//Foreachresponse,itparsesthereceivedstringasJSON,convertsthatobjectandreturnssastringconstnet=require(`net`);consthttp=require(`http`);functionrenderAnimalString(jsonString){constdata=JSON.parse(jsonString);return`${data.test}:yourarea${data.type}andyouhave${data.feet}feet.`;}/*----------------*//*--NETserver--*//*----------------*/net.createServer((socket)=>{socket.on(`data`,(jsonString)=>{socket.end(renderAnimalString(jsonString));});}).listen(8888);/*----------------*//*--HTTPserver--*//*--------------------*/functionparseIncomingMessage(res){returnnewPromise((resolve)=>{letdata=``;res.on(`data`,(chunk)=>{data+=chunk;});res.on(`end`,()=>resolve(data));});}http.createServer().listen(8080).on(`request`,(req,res)=>{parseIncomingMessage(req).then((jsonString)=>{res.end(renderAnimalString(jsonString));});});REPLtricks如果你是REPL模式,就是直接进入node,然后进入交互模式。你可以直接输入.loadsomeFile.js然后你可以加载一个包含自定义常量的文件。您可以通过设置NODE_REPL_HISTORY=""来避免将日志写入文件。_用于记录最后一次计算的值。REPL启动后,所有模块直接加载成功。可以与os.arch()一起使用,而不是require(os).arch()。