成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

我在閱讀NodeJS文檔中讀出的19個套路

開發(fā) 后端
雖然我已經用了三年多的NodeJS,也曾經以為自己對其無所不知。但是我好像從未有安靜的坐下來仔細地閱讀NodeJS的完整文檔。如果有熟悉我的朋友應該知道,我之前已經看了HTML,DOM,Web APIs,CSS,SVG以及ECMAScript的文檔,NodeJS是我這個系列的最后一個待翻閱的山峰。在閱讀文檔的過程中我也發(fā)現了很多本來不知道的知識,我覺得我有必要分享給大家。不過文檔更多的是平鋪直敘,因此我也以閱讀的順序列舉出我覺得需要了解的點。

雖然我已經用了三年多的NodeJS,也曾經以為自己對其無所不知。但是我好像從未有安靜的坐下來仔細地閱讀NodeJS的完整文檔。如果有熟悉我的朋友應該知道,我之前已經看了HTML,DOM,Web APIs,CSS,SVG以及ECMAScript的文檔,NodeJS是我這個系列的最后一個待翻閱的山峰。在閱讀文檔的過程中我也發(fā)現了很多本來不知道的知識,我覺得我有必要分享給大家。不過文檔更多的是平鋪直敘,因此我也以閱讀的順序列舉出我覺得需要了解的點。

querystring:可以用作通用解析器的模塊

很多時候我們會從數據庫或其他地方得到這種奇怪格式的字符串:name:Sophie;shape:fox;condition:new,一般來說我們會利用字符串切割的方式來講字符串劃分到JavaScript Object。不過querystring也是個不錯的現成的工具:

 

  1. const weirdoString = `name:Sophie;shape:fox;condition:new`;  
  2. const result = querystring.parse(weirdoString, `;`, `:`);  
  3. // result:  
  4. // {  
  5. // name: `Sophie`,  
  6. // shape: `fox`,  
  7. // condition: `new`,  
  8. // }; 

V8 Inspector

以--inspect參數運行你的Node應用程序,它會反饋你某個URL。將該URL復制到Chrome中并打開,你就可以使用Chrome DevTools來調試你的Node應用程序啦。詳細的實驗可以參考這篇文章。不過需要注意的是,該參數仍然屬于實驗性質。

我在閱讀NodeJS文檔中讀出的19個套路

nextTick 與 setImmediate的區(qū)別

這兩貨的區(qū)別可能光從名字上還看不出來,我覺得應該給它們取個別名:

  • process.nextTick()應該為process.sendThisToTheStartOfTheQueue()
  • setImmediate應該為sendThisToTheEndOfTheQueue()

再說句不相關的,React中的Props應該為stuffThatShouldStayTheSameIfTheUserRefreshes,而State應該為stuffThatShouldBeForgottenIfTheUserRefreshes。

Server.listen 可以使用Object作為參數

我更喜歡命名參數的方式調用函數,這樣相較于僅按照順序的無命名參數法會更直觀。別忘了Server.listen也可以使用某個Object作為參數:

 

  1. require(`http`)  
  2. .createServer()  
  3. .listen({  
  4. port: 8080,  
  5. host: `localhost`,  
  6. })  
  7. .on(`request`, (req, res) => {  
  8. res.end(`Hello World!`);  
  9. }); 

不過這個特性不是表述在http.Server這個API中,而是在其父級net.Server的文檔中。

相對地址

你傳入fs模塊的距離可以是相對地址,即相對于process.cwd()。估計有些人早就知道了,不過我之前一直以為是只能使用絕對地址:

 

  1. const fs = require(`fs`);  
  2. const path = require(`path`);  
  3. // why have I always done this...  
  4. fs.readFile(path.join(__dirname, `myFile.txt`), (err, data) => {  
  5. // do something  
  6. });  
  7. // when I could just do this?  
  8. fs.readFile(`./path/to/myFile.txt`, (err, data) => {  
  9. // do something  
  10. }); 

Path Parsing:路徑解析

之前我一直不知道的某個功能就是從某個文件名中解析出路徑,文件名,文件擴展等等:

 

  1. myFilePath = `/someDir/someFile.json`;  
  2. path.parse(myFilePath).base === `someFile.json`; // true  
  3. path.parse(myFilePath).name === `someFile`; // true  
  4. path.parse(myFilePath).ext === `.json`; // true 

Logging with colors

別忘了console.dir(obj,{colors:true})能夠以不同的色彩打印出鍵與值,這一點會大大增加日志的可讀性。

使用setInterval執(zhí)行定時任務

我喜歡使用setInterval來定期執(zhí)行數據庫清理任務,不過默認情況下在存在setInterval的時候NodeJS并不會退出,你可以使用如下的方法讓Node沉睡:

 

  1. const dailyCleanup = setInterval(() => {  
  2. cleanup();  
  3. }, 1000 * 60 * 60 * 24);  
  4. dailyCleanup.unref();  
  5. Use Signal Constants 

如果你嘗試在NodeJS中殺死某個進程,估計你用過如下語法:

  1. process.kill(process.pid, `SIGTERM`); 

這個沒啥問題,不過既然第二個參數同時能夠使用字符串與整形變量,那么還不如使用全局變量呢:

  1. process.kill(process.pid, os.constants.signals.SIGTERM); 

IP Address Validation

NodeJS中含有內置的IP地址校驗工具,這一點可以免得你寫額外的正則表達式:

 

  1. require(`net`).isIP(`10.0.0.1`) 返回 4  
  2. require(`net`).isIP(`cats`) 返回 0 

os.EOF

不知道你有沒有手寫過行結束符,看上去可不漂亮啊。NodeJS內置了os.EOF,其在Windows下是rn,其他地方是n,使用os.EOL能夠讓你的代碼在不同的操作系統(tǒng)上保證一致性:

 

  1. const fs = require(`fs`);  
  2. // bad  
  3. fs.readFile(`./myFile.txt`, `utf8`, (err, data) => {  
  4. data.split(`\r\n`).forEach(line => {  
  5. // do something  
  6. });  
  7. });  
  8. // good  
  9. const os = require(`os`);  
  10. fs.readFile(`./myFile.txt`, `utf8`, (err, data) => {  
  11. data.split(os.EOL).forEach(line => {  
  12. // do something  
  13. });  
  14. }); 

HTTP 狀態(tài)碼

NodeJS幫我們內置了HTTP狀態(tài)碼及其描述,也就是http.STATUS_CODES,鍵為狀態(tài)值,值為描述:

我在閱讀NodeJS文檔中讀出的19個套路

你可以按照如下方法使用:

 

  1. someResponse.code === 301; // true  
  2. require(`http`).STATUS_CODES[someResponse.code] === `Moved Permanently`; // true 

避免異常崩潰

有時候碰到如下這種導致服務端崩潰的情況還是挺無奈的:

 

  1. const jsonData = getDataFromSomeApi(); // But oh no, bad data!  
  2. const data = JSON.parse(jsonData); // Loud crashing noise. 

我為了避免這種情況,在全局加上了一個:

  1. process.on(`uncaughtException`, console.error); 

當然,這種辦法絕不是最佳實踐,如果是在大型項目中我還是會使用PM2,然后將所有可能崩潰的代碼加入到try...catch中。

Just this once()

除了on方法,once方法也適用于所有的EventEmitters,希望我不是最后才知道這個的:

  1. server.once(`request`, (req, res) => res.end(`No more from me.`)); 

Custom Console

你可以使用new console.Console(standardOut,errorOut),然后設置自定義的輸出流。你可以選擇創(chuàng)建console將數據輸出到文件或者Socket或者第三方中。

DNS lookup

某個年輕人告訴我,Node并不會緩存DNS查詢信息,因此你在使用URL之后要等個幾毫秒才能獲取到數據。不過其實你可以使用dns.lookup()來緩存數據:

 

  1. dns.lookup(`www.myApi.com`, 4, (err, address) => {  
  2. cacheThisForLater(address);  
  3. }); 

fs 在不同OS上有一定差異

  • fs.stats()返回的對象中的mode屬性在Windows與其他操作系統(tǒng)中存在差異。
  • fs.lchmod()僅在macOS中有效。
  • 僅在Windows中支持調用fs.symlink()時使用type參數。
  • 僅僅在macOS與Windows中調用fs.watch()時傳入recursive選項。
  • 在Linux與Windows中fs.watch()的回調可以傳入某個文件名
  • 使用fs.open()以及a+屬性打開某個目錄時僅僅在FreeBSD以及Windows上起作用,在macOS以及Linux上則存在問題。
  • 在Linux下以追加模式打開某個文件時,傳入到fs.write()的position參數會被忽略。

net 模塊差不多比http快上兩倍

筆者在文檔中看到一些關于二者性能的討論,還特地運行了兩個服務器來進行真實比較。結果來看http.Server大概每秒可以接入3400個請求,而net.Server可以接入大概5500個請求。

 

  1. // This makes two connections, one to a tcp server, one to an http server (both in server.js)  
  2. // It fires off a bunch of connections and times the response  
  3. // Both send strings.  
  4. const net = require(`net`);  
  5. const http = require(`http`);  
  6. function parseIncomingMessage(res) {  
  7. return new Promise((resolve) => {  
  8. let data = ``;  
  9. res.on(`data`, (chunk) => {  
  10. data += chunk;  
  11. });  
  12. res.on(`end`, () => resolve(data));  
  13. });  
  14.  
  15. const testLimit = 5000;  
  16. /* ------------------ */  
  17. /* -- NET client -- */  
  18. /* ------------------ */  
  19. function testNetClient() {  
  20. const netTest = {  
  21. startTime: process.hrtime(),  
  22. responseCount: 0,  
  23. testCount: 0,  
  24. payloadData: {  
  25. type: `millipede`,  
  26. feet: 100,  
  27. test: 0,  
  28. },  
  29. };  
  30. function handleSocketConnect() {  
  31. netTest.payloadData.test++;  
  32. netTest.payloadData.feet++;  
  33. const payload = JSON.stringify(netTest.payloadData);  
  34. this.end(payload, `utf8`);  
  35.  
  36. function handleSocketData() {  
  37. netTest.responseCount++;  
  38. if (netTest.responseCount === testLimit) {  
  39. const hrDiff = process.hrtime(netTest.startTime); 
  40.  const elapsedTime = hrDiff[0] * 1e3 + hrDiff[1] / 1e6;  
  41. const requestsPerSecond = (testLimit / (elapsedTime / 1000)).toLocaleString();  
  42. console.info(`net.Server handled an average of ${requestsPerSecond} requests per second.`);  
  43.  
  44.  
  45. while (netTest.testCount < testLimit) {  
  46. netTest.testCount++;  
  47. const socket = net.connect(8888, handleSocketConnect);  
  48. socket.on(`data`, handleSocketData);  
  49.  
  50.  
  51. /* ------------------- */  
  52. /* -- HTTP client -- */  
  53. /* ------------------- */  
  54. function testHttpClient() {  
  55. const httpTest = {  
  56. startTime: process.hrtime(),  
  57. responseCount: 0, 
  58.  testCount: 0,  
  59. };  
  60. const payloadData = {  
  61. type: `centipede`,  
  62. feet: 100,  
  63. test: 0,  
  64. };  
  65. const options = {  
  66. hostname: `localhost`,  
  67. port: 8080,  
  68. method: `POST`,  
  69. headers: {  
  70. 'Content-Type': `application/x-www-form-urlencoded`,  
  71. },  
  72. };  
  73. function handleResponse(res) {  
  74. parseIncomingMessage(res).then(() => {  
  75. httpTest.responseCount++;  
  76. if (httpTest.responseCount === testLimit) {  
  77. const hrDiff = process.hrtime(httpTest.startTime);  
  78. const elapsedTime = hrDiff[0] * 1e3 + hrDiff[1] / 1e6;  
  79. const requestsPerSecond = (testLimit / (elapsedTime / 1000)).toLocaleString();  
  80. console.info(`http.Server handled an average of ${requestsPerSecond} requests per second.`);  
  81.  
  82. });  
  83.  
  84. while (httpTest.testCount < testLimit) {  
  85. httpTest.testCount++;  
  86. payloadData.test = httpTest.testCount;  
  87. payloadData.feet++;  
  88. const payload = JSON.stringify(payloadData);  
  89. options[`Content-Length`] = Buffer.byteLength(payload);  
  90. const req = http.request(options, handleResponse);  
  91. req.end(payload);  
  92.  
  93.  
  94. /* -- Start tests -- */  
  95. // flip these occasionally to ensure there's no bias based on order  
  96. setTimeout(() => {  
  97. console.info(`Starting testNetClient()`); 
  98.  testNetClient();  
  99. }, 50);  
  100. setTimeout(() => {  
  101. console.info(`Starting testHttpClient()`);  
  102. testHttpClient();  
  103. }, 2000);  
  104. // This sets up two servers. A TCP and an HTTP one.  
  105. // For each response, it parses the received string as JSON, converts that object and returns a string  
  106. const net = require(`net`);  
  107. const http = require(`http`);  
  108. function renderAnimalString(jsonString) {  
  109. const data = JSON.parse(jsonString);  
  110. return `${data.test}: your are a ${data.type} and you have ${data.feet} feet.`;  
  111.  
  112. /* ------------------ */  
  113. /* -- NET server -- */  
  114. /* ------------------ */  
  115. net  
  116. .createServer((socket) => {  
  117. socket.on(`data`, (jsonString) => {  
  118. socket.end(renderAnimalString(jsonString));  
  119. });  
  120. })  
  121. .listen(8888);  
  122. /* ------------------- */  
  123. /* -- HTTP server -- */  
  124. /* ------------------- */  
  125. function parseIncomingMessage(res) {  
  126. return new Promise((resolve) => {  
  127. let data = ``;  
  128. res.on(`data`, (chunk) => {  
  129. data += chunk;  
  130. });  
  131. res.on(`end`, () => resolve(data));  
  132. });  
  133.  
  134. http  
  135. .createServer()  
  136. .listen(8080)  
  137. .on(`request`, (req, res) => {  
  138. parseIncomingMessage(req).then((jsonString) => {  
  139. res.end(renderAnimalString(jsonString));  
  140. });  
  141. }); 

REPL tricks

  • 如果你是在REPL模式下,就是直接輸入node然后進入交互狀態(tài)的模式。你可以直接輸入.load someFile.js然后可以載入包含自定義常量的文件。
  • 可以通過設置NODE_REPL_HISTORY=""來避免將日志寫入到文件中。
  • _用來記錄最后一個計算值。
  • 在REPL啟動之后,所有的模塊都已經直接加載成功。可以使用os.arch()而不是require(os).arch()來使用。

 

責任編輯:未麗燕 來源: segmentfault
相關推薦

2017-10-23 12:22:58

Android編程基礎總結

2020-02-10 09:23:09

LinuxReddit命令

2019-04-22 08:39:13

Leader開發(fā)規(guī)范開發(fā)流程

2021-05-24 11:21:25

老板員工組織

2021-02-03 19:46:01

工具Snipaste軟件開發(fā)

2018-06-15 09:57:37

架構技術棧微信半月刊

2018-05-23 10:04:24

MySQL查詢優(yōu)化

2013-01-30 10:28:06

閱讀方法編程書籍程序員

2022-11-04 19:00:00

架構

2018-06-04 08:55:15

技術套路開發(fā)

2018-01-12 14:57:06

React Nativ開發(fā)錯誤

2019-05-23 14:36:24

LinuxSOSReportxsos

2016-05-24 10:40:32

NodeJS總結

2011-08-31 11:04:14

windows7文檔

2017-05-22 10:54:56

深度學習CNNMNIST

2023-08-13 16:32:12

JavaScript

2018-01-03 10:32:21

面試經驗套路

2020-10-09 09:40:59

GNOME桌面主題桌面應用

2021-11-11 09:07:04

CSS 技巧唯美的邊框

2015-10-08 08:46:29

職業(yè)建議
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲国产成人精品久久久国产成人一区 | 少妇av片 | 国产亚洲精品久久久久久豆腐 | 一区二区三区四区在线播放 | 久久久久久久久91 | 亚洲视频免费播放 | 日本小电影网站 | 精品国产不卡一区二区三区 | 久久国产精品99久久久久 | 国产成人在线播放 | 免费在线观看黄色av | 中文字幕亚洲精品 | 亚洲精品一区二区三区中文字幕 | 久久免费精品 | 老牛嫩草一区二区三区av | 久在线| 96av麻豆蜜桃一区二区 | 亚洲精品在线视频 | 国产最好的av国产大片 | 国产精品久久久久婷婷二区次 | 福利视频亚洲 | 国产一区二区激情视频 | 在线观看免费毛片 | 国产精品乱码一区二三区小蝌蚪 | 精品亚洲一区二区三区 | a级片在线观看 | 日日噜噜噜夜夜爽爽狠狠视频97 | 色综合久| av在线免费观看网址 | 久久美女视频 | 我要看免费一级毛片 | 人人草人人干 | 国产精品日日摸夜夜添夜夜av | 欧美一级免费看 | 天天色综 | 色婷婷综合网 | 中文字幕不卡在线观看 | 欧美极品在线观看 | 91热在线 | 国产精品一区在线 | 成人三级网址 |