十年網(wǎng)站開發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營(yíng)維護(hù)+專業(yè)推廣+無(wú)憂售后,網(wǎng)站問題一站解決
NodeJS開發(fā)常見的錯(cuò)誤有哪些?很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來(lái)學(xué)習(xí)下,希望你能有所收獲。
Nodejs 誕生于 2009 年,由于它使用了 JavaScript ,在這些年里獲得了非常廣泛的流行。它是一個(gè)用于編寫服務(wù)器端應(yīng)用程序的 JavaScript 運(yùn)行時(shí),但是 "它就是JavaScript" 這句話并不是 100% 正確的。
JavaScript 是單線程的,它不是被設(shè)計(jì)用來(lái)實(shí)現(xiàn)要求可伸縮性的服務(wù)器端上運(yùn)行的。借助 Google Chrome 的高性能 V8 JavaScript 引擎, libuv 的超酷異步 I/O 實(shí)現(xiàn)以及其他一些刺激性的補(bǔ)充, Nodejs 能夠?qū)⒖蛻舳?JavaScript 引入服務(wù)器端,從而能夠編寫超快速的、能夠處理成千上萬(wàn)的套接字連接的 Web JavaScript 服務(wù)器。
NodeJS 是一個(gè)由大量有趣的基礎(chǔ)模塊構(gòu)建的大型平臺(tái)。但是,由于對(duì) NodeJS 的這些內(nèi)部組件的工作方式缺乏了解,因此許多 NodeJS 開發(fā)人員對(duì) 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ī)制。它以特定順序處理來(lái)自不同類型的異步事件的完成事件。
相反, NodeJS Event Emitter 是一個(gè)核心的 NodeJS API ,它允許你將監(jiān)聽器函數(shù)附加到一個(gè)特定的事件,這個(gè)事件一旦觸發(fā)就會(huì)被調(diào)用。這種行為看起來(lái)像是異步的,因?yàn)槭录幚沓绦虻恼{(diào)用時(shí)間通常比它最初作為事件處理程序注冊(cè)的時(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 對(duì)象,其中對(duì)象屬性是事件名稱,屬性的值是一個(gè)偵聽器函數(shù)或偵聽器函數(shù)數(shù)組。
當(dāng)在 EventEmitter 實(shí)例上調(diào)用 emit 函數(shù)時(shí), emitter 將按順序依次同步調(diào)所有注冊(cè)到示例上的回調(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); });