日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
我在閱讀NodeJS文檔中讀出的19個套路

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

10年的和政網(wǎng)站建設經(jīng)驗,針對設計、前端、開發(fā)、售后、文案、推廣等六對一服務,響應快,48小時及時工作處理。成都全網(wǎng)營銷的優(yōu)勢是能夠根據(jù)用戶設備顯示端的尺寸不同,自動調(diào)整和政建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設計,從而大程度地提升瀏覽體驗。創(chuàng)新互聯(lián)建站從事“和政網(wǎng)站設計”,“和政網(wǎng)站推廣”以來,每個客戶項目都認真落實執(zhí)行。

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

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

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

nextTick 與 setImmediate的區(qū)別

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

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

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

Server.listen 可以使用Object作為參數(shù)

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

 
 
  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í)行數(shù)據(jù)庫清理任務,不過默認情況下在存在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`);

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

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

IP Address Validation

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

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

os.EOF

不知道你有沒有手寫過行結束符,看上去可不漂亮啊。NodeJS內(nèi)置了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幫我們內(nèi)置了HTTP狀態(tài)碼及其描述,也就是http.STATUS_CODES,鍵為狀態(tài)值,值為描述:

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

 
 
  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將數(shù)據(jù)輸出到文件或者Socket或者第三方中。

DNS lookup

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

 
 
  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中支持調(diào)用fs.symlink()時使用type參數(shù)。
  • 僅僅在macOS與Windows中調(diào)用fs.watch()時傳入recursive選項。
  • 在Linux與Windows中fs.watch()的回調(diào)可以傳入某個文件名
  • 使用fs.open()以及a+屬性打開某個目錄時僅僅在FreeBSD以及Windows上起作用,在macOS以及Linux上則存在問題。
  • 在Linux下以追加模式打開某個文件時,傳入到fs.write()的position參數(shù)會被忽略。

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

REPL tricks

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

分享標題:我在閱讀NodeJS文檔中讀出的19個套路
網(wǎng)頁URL:http://www.dlmjj.cn/article/djishch.html