亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

NodeJS開發(fā)人員常見五個(gè)錯(cuò)誤理解

 更新時(shí)間:2020年10月14日 11:31:56   作者:酷兒q  
這篇文章主要介紹了NodeJS開發(fā)人員常見五個(gè)錯(cuò)誤理解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

Nodejs 誕生于 2009 年,由于它使用了 JavaScript ,在這些年里獲得了非常廣泛的流行。它是一個(gè)用于編寫服務(wù)器端應(yīng)用程序的 JavaScript 運(yùn)行時(shí),但是 "它就是JavaScript" 這句話并不是 100% 正確的。

JavaScript 是單線程的,它不是被設(shè)計(jì)用來實(shí)現(xiàn)要求可伸縮性的服務(wù)器端上運(yùn)行的。借助 Google Chrome 的高性能 V8 JavaScript 引擎, libuv 的超酷異步 I/O 實(shí)現(xiàn)以及其他一些刺激性的補(bǔ)充, Nodejs 能夠?qū)⒖蛻舳?JavaScript 引入服務(wù)器端,從而能夠編寫超快速的、能夠處理成千上萬的套接字連接的 Web JavaScript 服務(wù)器。

NodeJS 是一個(gè)由大量有趣的基礎(chǔ)模塊構(gòu)建的大型平臺(tái)。但是,由于對 NodeJS 的這些內(nèi)部組件的工作方式缺乏了解,因此許多 NodeJS 開發(fā)人員對 NodeJS 的行為做出了錯(cuò)誤的理解,并開發(fā)了導(dǎo)致嚴(yán)重性能問題以及難以跟蹤的錯(cuò)誤的應(yīng)用程序。在本文中,我將描述在許多 NodeJS 開發(fā)人員中很常見的五個(gè)錯(cuò)誤理解。

誤解1 — EventEmitter 和事件循環(huán)相關(guān)

編寫 NodeJS 應(yīng)用程序時(shí)會(huì)大量使用 NodeJS EventEmitter ,但是人們誤認(rèn)為 EventEmitter 與 NodeJS Event Loop 有關(guān),這是不正確的。

NodeJS 事件循環(huán)是 NodeJS 的核心,它為 NodeJS 提供了異步的,非阻塞的 I/O 機(jī)制。它以特定順序處理來自不同類型的異步事件的完成事件。

相反, NodeJS Event Emitter 是一個(gè)核心的 NodeJS API ,它允許你將監(jiān)聽器函數(shù)附加到一個(gè)特定的事件,這個(gè)事件一旦觸發(fā)就會(huì)被調(diào)用。這種行為看起來像是異步的,因?yàn)槭录幚沓绦虻恼{(diào)用時(shí)間通常比它最初作為事件處理程序注冊的時(shí)間晚。

EventEmitter 實(shí)例跟蹤與 EventEmitter 實(shí)例本身內(nèi)的事件相關(guān)聯(lián)的所有事件和其實(shí)例本身。它不會(huì)在事件循環(huán)隊(duì)列中調(diào)度任何事件。存儲(chǔ)此信息的數(shù)據(jù)結(jié)構(gòu)只是一個(gè)普通的老式 JavaScript 對象,其中對象屬性是事件名稱,屬性的值是一個(gè)偵聽器函數(shù)或偵聽器函數(shù)數(shù)組。

當(dāng)在 EventEmitter 實(shí)例上調(diào)用 emit 函數(shù)時(shí), emitter 將按順序依次同步調(diào)所有注冊到示例上的回調(diào)函數(shù)。

看以下代碼片段:

const EventEmitter = require('events');

const myEmitter = new EventEmitter();

myEmitter.on('myevent', () => console.log('handler1: myevent was fired!'));
myEmitter.on('myevent', () => console.log('handler2: myevent was fired!'));
myEmitter.on('myevent', () => console.log('handler3: myevent was fired!'));

myEmitter.emit('myevent');
console.log('I am the last log line');

以上代碼段的輸出為:

handler1: myevent was fired!
handler2: myevent was fired!
handler3: myevent was fired!
I am the last log line

由于 event emitter 同步執(zhí)行所有事件處理函數(shù),因此 I am the last log line 在調(diào)用所有監(jiān)聽函數(shù)完成之后才會(huì)打印。

誤解2 - 所有接受回調(diào)的函數(shù)都是異步的

函數(shù)是同步的還是異步的取決于函數(shù)在執(zhí)行期間是否創(chuàng)建異步資源。根據(jù)這個(gè)定義,如果給你一個(gè)函數(shù),你可以確定給定的函數(shù)是異步的:

JavaScript

NodeJS
setTimeout,setInterval,setImmediate,process.nextTick

NodeJS API

child_process,fs,net
PromiseAPI
async-await

從 C++ 插件調(diào)用一個(gè)函數(shù),該函數(shù)被編寫為異步函數(shù)(例如 bcrypt )

接受回調(diào)函數(shù)作為參數(shù)不會(huì)使函數(shù)異步。但是,通常異步函數(shù)的確接受回調(diào)作為最后一個(gè)參數(shù)(除非包裝返回一個(gè) Promise )。接受回調(diào)并將結(jié)果傳遞給回調(diào)的這種模式稱為 Continuation Passing Style 。你仍然可以使用 Continuation Passing Style 編寫同步功能。

const sum = (a, b, callback) => {
 callback(a + b);
};

sum(1,2, (result) => {
 console.log(result);
});

同步函數(shù)和異步函數(shù)在執(zhí)行期間在如何使用堆棧方面有很大的不同。同步函數(shù)在執(zhí)行的整個(gè)過程中都會(huì)占用堆棧,方法是禁止其他任何人占用堆棧直到return 為止。相反,異步函數(shù)調(diào)度一些異步任務(wù)并立即返回,因此將自身從堆棧中刪除。一旦預(yù)定的異步任務(wù)完成,將調(diào)用提供的任何回調(diào),并且該回調(diào)函數(shù)將再次占據(jù)該堆棧。此時(shí),啟動(dòng)異步任務(wù)的函數(shù)將不再可用,因?yàn)樗呀?jīng)返回。

考慮到以上定義,請嘗試確定以下函數(shù)是異步還是同步。

function writeToMyFile(data, callback) {
  if (!data) {
    callback(new Error('No data provided'));
  } else {
    fs.writeFile('myfile.txt', data, callback);
  }
}

實(shí)際上,上述函數(shù)可以是同步的,也可以是異步的,具體取決于傳遞給的值 data 。

如果 data 為 false, callback 則將立即調(diào)用,并出現(xiàn)錯(cuò)誤。在此執(zhí)行路徑中,該功能是 100% 同步的,因?yàn)樗粓?zhí)行任何異步任務(wù)。

如果 data 是 true ,它會(huì)將 data 寫入 myfile.txt ,將調(diào)用回調(diào)完成的文件 I/O 操作之后。由于異步文件 I/O 操作,此執(zhí)行路徑是100%異步的。

強(qiáng)烈建議不要以這種不一致的方式(在此功能同時(shí)執(zhí)行同步和異步操作)編寫函數(shù),因?yàn)檫@會(huì)使應(yīng)用程序的行為無法預(yù)測。幸運(yùn)的是,這些不一致可以很容易地修復(fù)如下:

function writeToMyFile(data, callback) {
  if (!data) {
    process.nextTick(() => callback(new Error('No data provided')));
  } else {
    fs.writeFile('myfile.txt', data, callback);
  }
}

process.nextTick 可以用來延遲 callback 函數(shù)的調(diào)用,從而使執(zhí)行路徑異步。

或者,你可以使用 setImmediate 代替 process.nextTick ,這或多或少會(huì)產(chǎn)生相同的結(jié)果。但是,process.nextTick相對而言,回調(diào)具有更高的優(yōu)先級(jí),從而使其比 setImmediate 更快。

誤解3 - 所有占用大量CPU的功能都在阻止事件循環(huán)

眾所周知, CPU 密集型操作會(huì)阻塞 Node.js 事件循環(huán)。盡管這句話在一定程度上是正確的,但并不是100%正確,因?yàn)橛行?CPU 密集型函數(shù)不會(huì)阻塞事件循環(huán)。

一般來說,加密操作和壓縮操作是受 CPU 高度限制的。由于這個(gè)原因,某些加密函數(shù)和 zlib 函數(shù)的異步版本以在 libuv 線程池上執(zhí)行計(jì)算的方式編寫,這樣它們就不會(huì)阻塞事件循環(huán)。其中一些功能是:

  • crypto.pbkdf2()
  • crypto.randomFill()
  • crypto.randomBytes()
  • 所有 zlib 異步功能

但是,在撰寫本文時(shí),還無法使用純 JavaScript 在 libuv 線程池上運(yùn)行CPU密集型操作。但是,你可以編寫自己的 C++ 插件,使你能夠安排 libuv 線程池上的工作。有某些第三方庫(例如 bcrypt ),它們執(zhí)行CPU密集型操作并使用 C++ 插件來實(shí)現(xiàn)針對CPU綁定操作的異步API。

誤解4 - 所有異步操作都在線程池上執(zhí)行

現(xiàn)代操作系統(tǒng)具有內(nèi)置的內(nèi)核支持,可使用事件通知(例如, Linux 中的 epoll , macOS 中的 kqueue , Windows 中的 IOCP 等)以有效的方式促進(jìn)網(wǎng)絡(luò) I/O 操作的本機(jī)異步。因此,不會(huì)在 libuv 線程池上執(zhí)行網(wǎng)絡(luò) I/O 。

但是,當(dāng)涉及到文件 I/O 時(shí),跨操作系統(tǒng)以及同一操作系統(tǒng)中的某些情況存在許多不一致之處。這使得為文件 I/O 實(shí)現(xiàn)通用的獨(dú)立于平臺(tái)的 API 極為困難。因此,在 libuv 線程池上執(zhí)行文件系統(tǒng)操作以公開一致的異步 API 。

dns.lookup() dns 模塊中的函數(shù)是另一個(gè)利用 libuv 線程池的API。原因是,使用 dns.lookup() 功能將域名解析為IP地址是與平臺(tái)有關(guān)的操作,并且此操作不是 100% 的網(wǎng)絡(luò) I/O 。

誤解5 - 不應(yīng)使用NodeJS編寫CPU密集型應(yīng)用程序

這并不是真正的誤解,而是關(guān)于 NodeJS 的一個(gè)眾所周知的事實(shí),現(xiàn)在由于在 Node v10.5.0 中引入 Worker Threads 而被淘汰了。盡管它是作為實(shí)驗(yàn)性功能引入的,但 worker_threads 自 Node v12 LTS 起,該模塊現(xiàn)已穩(wěn)定,因此適合在具有CPU密集型操作的生產(chǎn)應(yīng)用程序中使用。

每個(gè) Node.js 工作線程將擁有其自己的v8運(yùn)行時(shí)的副本,事件循環(huán)和 libuv 線程池。因此,執(zhí)行阻塞CPU密集型操作的一個(gè)工作線程不會(huì)影響其他工作線程的事件循環(huán),從而使它們可用于任何傳入的工作。

但是,在撰寫本文時(shí),IDE對 Worker Threads 的支持還不是最大。某些IDE不支持將調(diào)試器附加到在主線程以外的其他線程中運(yùn)行的代碼。但是,隨著許多開發(fā)人員已經(jīng)開始采用輔助線程進(jìn)行CPU綁定的操作(例如視頻編碼等),開發(fā)支持將隨著時(shí)間的推移而成熟。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Node服務(wù)端實(shí)戰(zhàn)之操作數(shù)據(jù)庫示例詳解

    Node服務(wù)端實(shí)戰(zhàn)之操作數(shù)據(jù)庫示例詳解

    這篇文章主要為大家介紹了Node服務(wù)端實(shí)戰(zhàn)之操作數(shù)據(jù)庫示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • Node Sass依賴問題排查思路解析

    Node Sass依賴問題排查思路解析

    這篇文章主要為大家介紹了Node Sass依賴問題排查思路解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • NodeJS Web應(yīng)用監(jiān)聽sock文件實(shí)例

    NodeJS Web應(yīng)用監(jiān)聽sock文件實(shí)例

    這篇文章主要介紹了NodeJS Web應(yīng)用監(jiān)聽sock文件實(shí)例,本文講解 NodeJS 的 TCP 和 HTTP 監(jiān)聽 Domain Socket 文件例子,需要的朋友可以參考下
    2015-02-02
  • node.js中npm包管理工具用法分析

    node.js中npm包管理工具用法分析

    這篇文章主要介紹了node.js中npm包管理工具用法,結(jié)合實(shí)例形式分析了node.js中npm包管理工具查看、安裝、更新、卸載等相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下
    2020-02-02
  • npm?install常見報(bào)錯(cuò)以及問題詳解

    npm?install常見報(bào)錯(cuò)以及問題詳解

    npm?install總是一言難盡,下面這篇文章主要給大家介紹了關(guān)于npm?install常見報(bào)錯(cuò)以及問題的相關(guān)資料,文中通過圖文以及實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-02-02
  • node.js中的fs.chmodSync方法使用說明

    node.js中的fs.chmodSync方法使用說明

    這篇文章主要介紹了node.js中的fs.chmodSync方法使用說明,本文介紹了fs.chmodSync方法說明、語法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下
    2014-12-12
  • node.js express捕獲全局異常的三種方法實(shí)例分析

    node.js express捕獲全局異常的三種方法實(shí)例分析

    這篇文章主要介紹了node.js express捕獲全局異常的三種方法,結(jié)合實(shí)例形式簡單分析了node.js express捕獲全局異常的常見操作方法與使用注意事項(xiàng),需要的朋友可以參考下
    2019-12-12
  • 輕松創(chuàng)建nodejs服務(wù)器(10):處理POST請求

    輕松創(chuàng)建nodejs服務(wù)器(10):處理POST請求

    這篇文章主要介紹了輕松創(chuàng)建nodejs服務(wù)器(10):處理POST請求,本文告訴你如何實(shí)現(xiàn)在node.js中處理POST請求,需要的朋友可以參考下
    2014-12-12
  • npm?install總是卡住不動(dòng)問題的解決辦法

    npm?install總是卡住不動(dòng)問題的解決辦法

    在我們安裝完Node.js之后,需要使用npm命令來安裝一些工具,下面這篇文章主要給大家介紹了關(guān)于npm?install總是卡住不動(dòng)問題的解決辦法,需要的朋友可以參考下
    2022-05-05
  • package.json的版本號(hào)更新優(yōu)化方法

    package.json的版本號(hào)更新優(yōu)化方法

    這篇文章主要為大家介紹了package.json的版本號(hào)更新優(yōu)化方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04

最新評論