溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

常見的Node.js面試問題有哪些

發(fā)布時間:2021-10-19 09:57:20 來源:億速云 閱讀:187 作者:iii 欄目:web開發(fā)

這篇文章主要介紹“常見的Node.js面試問題有哪些”,在日常操作中,相信很多人在常見的Node.js面試問題有哪些問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”常見的Node.js面試問題有哪些”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

1. Node.js 與 JavaScript 有什么不同?

常見的Node.js面試問題有哪些

2. 什么時候用 Node.js?

Node.js  是異步的、事件驅(qū)動的、非阻塞的和單線程的,使得它成為開發(fā)下面應(yīng)用程序的完美候選:

  • 實時應(yīng)用程序,如聊天和提供實時更新的應(yīng)用程序

  • 將視頻或其他多媒體內(nèi)容流式傳輸給大量觀眾的流式應(yīng)用程序

  • 其他 I/O 密集型應(yīng)用程序,如協(xié)作平臺

  • 遵循微服務(wù)架構(gòu)的網(wǎng)絡(luò)后端

然而,Node.js 的特性使得它對于其他類型的應(yīng)用程序來說不是一個理想的選擇。執(zhí)行 CPU 密集型任務(wù)的應(yīng)用程序(如復(fù)雜的數(shù)學(xué)計算)在使用 CPU  時表現(xiàn)不佳,因為 Node.js 是單線程的。

如果你想了解更多這方面的信息,請查看我們的文章 Node.js 架構(gòu)以及何時在項目中使用。

3. EventEmitter 做了什么?

Node.js 中任何對象發(fā)出的事件都是 EventEmitter 類的實例,就像 http 模塊。

所有 EventEmitter 類都可以使用 eventEmitter.on()  函數(shù)將事件偵聽器附加到事件。然后一旦捕捉到這樣的事件,就會同步地逐個調(diào)用它的偵聽器。

const events = require("events"); const eventEmitter = new events.EventEmitter(); const eventListener = function(){   console.log("event triggered"); } eventEmitter.on("emitted", eventListener); eventEmitter.emit("emitted");

4. 事件循環(huán)是什么?

單線程的 Node.js  必須是非阻塞的,以防止線程阻塞在需要很長時間才能完成的任務(wù)上,事件循環(huán)負(fù)責(zé)實現(xiàn)這種非阻塞行為,它使用應(yīng)用程序線程調(diào)度掛起的任務(wù)。

Node.js 在任務(wù)完成時通過回調(diào)來處理異步函數(shù)返回的響應(yīng)。與創(chuàng)建任務(wù)的事件類似,任務(wù)完成后也會發(fā)出一個事件。Node.js  將需要處理的事件添加到事件隊列。

事件循環(huán)對事件隊列中的事件進(jìn)行迭代,并安排何時執(zhí)行其關(guān)聯(lián)的回調(diào)函數(shù)。

5. 流是什么?

Stream 流是從源讀取或?qū)懭霐?shù)據(jù)并將其傳輸?shù)竭B續(xù)流目標(biāo)的管道。有四種類型:

  • 可讀

  • 可寫的

  • 可讀寫

  • 先寫入,再讀出來

每個流也是一個 EventEmitter。這意味著流對象可以在流上沒有數(shù)據(jù)、流上有可用數(shù)據(jù)或流中的數(shù)據(jù)在程序刷新時發(fā)出事件。

const fs = require("fs"); const readableStream = fs.createReadStream("test.txt"); let content = ""; readableStream.on("data", (chunk) => {   content += chunk; }); readableStream.on("end", () => {   console.log(content); });

6. readFile 和 createReadStream 函數(shù)有什么區(qū)別?

readFile 函數(shù)異步讀取文件的全部內(nèi)容,并存儲在內(nèi)存中,然后再傳遞給用戶。

createReadStream 使用一個可讀的流,逐塊讀取文件,而不是全部存儲在內(nèi)存中。

與 readFile 相比,createReadStream  使用更少的內(nèi)存和更快的速度來優(yōu)化文件讀取操作。如果文件相當(dāng)大,用戶不必等待很長時間直到讀取整個內(nèi)容,因為讀取時會先向用戶發(fā)送小塊內(nèi)容。

const fs = require("fs"); fs.readFile("test.txt", (err, content) => {   console.log(content); });

7. 如何處理 Node.js 中未捕獲的異常?

我們可以在進(jìn)程級別捕獲應(yīng)用程序中未捕獲的異常。為此將偵聽器附加到 process 全局對象:

process.on("uncaughtException", (err) => {   console.log("exception caught: ", err); });

8. Node.js 能否充分利用多核處理器?

(默認(rèn)的)Node.js 應(yīng)用程序總是單線程的,即使在多核處理器上運行,應(yīng)用程序也能只使用一個處理器。

但是 Node.js 的核心模塊之一 Cluster 支持 Node.js  應(yīng)用程序開啟多核,允許我們創(chuàng)建多個工作進(jìn)程,這些進(jìn)程可以在多個內(nèi)核上并行運行,并共享一個端口來偵聽事件。

每個進(jìn)程使用 IPC  與主線程通信,并根據(jù)需要將服務(wù)器句柄傳遞給其他進(jìn)程。主進(jìn)程可以偵聽端口本身并以循環(huán)方式將每個新連接傳遞給子進(jìn)程,也可以將端口分配給子進(jìn)程以便子進(jìn)程偵聽請求。

9. 反應(yīng)堆設(shè)計模式是什么?

反應(yīng)堆設(shè)計模式是,Node.js 將回調(diào)函數(shù)(處理程序)附加到每個 I/O  操作,然后創(chuàng)建請求時將處理程序提交給解復(fù)用器。

解復(fù)用器收集應(yīng)用程序中發(fā)出的每個 I/O  請求,并將它們作為隊列中的事件進(jìn)行排隊。這個隊列就是我們所說的事件隊列。將事件排隊后,解復(fù)用器返回應(yīng)用程序線程的控制。

同時,事件循環(huán)遍歷事件隊列中的每個事件,并調(diào)用附加的回調(diào)來處理事件響應(yīng)。

這就是 Node.js 中所使用的反應(yīng)堆模式。

10. 單線程與多線程網(wǎng)絡(luò)后端相比有哪些好處?

盡管 Node.js 是單線程的,但是大多數(shù)用于后端開發(fā)的編程語言都提供多線程來處理應(yīng)用程序操作。

為什么單線程有利于后端開發(fā)?

  • 開發(fā)人員更容易實現(xiàn)應(yīng)用程序。我們的應(yīng)用程序在生產(chǎn)過程中不會突然遇到意外的競爭條件。

  • 單線程應(yīng)用程序易于擴(kuò)展。

  • 它們可以毫不延遲地在一個時刻收到的大量用戶請求提供服務(wù)。相比之下,當(dāng)流量較大時,多線程后端必須等待線程池中的線程釋放,才能為用戶請求提供服務(wù)。利用  Node.js 的非阻塞特性,用戶請求不會在單個線程上掛起太長時間(只有在操作不是 CPU 密集型時)。

11. REPL 是什么?

REPL 代表 Read Eval Print Loop,是一個虛擬環(huán)境,可以在其中輕松地運行編程語言。Node.js  帶有一個內(nèi)置的 REPL 來運行 JavaScript 代碼,類似于我們在瀏覽器中用來運行 JavaScript 代碼的控制臺。

要啟動 Node.js REPL,只需在命令行上運行 node,然后寫一行 JavaScript 代碼,就可以在下一行看到它的輸出。

12. process.nextTick 和 setImmediate 有什么區(qū)別?

傳遞給 setImmediate  函數(shù)的回調(diào)將在事件隊列上的下一次迭代中執(zhí)行。

另一方面,回調(diào)傳遞給 process.nextTick  在下一次迭代之前以及程序中當(dāng)前運行的操作完成之后執(zhí)行。在應(yīng)用程序啟動時,開始遍歷事件隊列之前調(diào)用它的回調(diào)。

因此,回調(diào) process.nextTick 總是在 setImmediate 之前調(diào)用。

下面代碼段:

setImmediate(() => {   console.log("first"); }) process.nextTick(() => {   console.log("second"); }) console.log("third");

將按順序輸出:

third second first

13. stub 是什么?

測試應(yīng)用程序時使用 stub,模擬給定組件或模塊的行為,你可以將精力集中在要測試的代碼部分。通過使用 stub  代替與測試無關(guān)的組件,不必?fù)?dān)心外部組件會影響結(jié)果。

例如,如果正在測試的組件在預(yù)期測試的部分之前有一個文件讀取操作,則可以使用 stub 來模擬該行為并返回模擬內(nèi)容,而不用實際讀取文件。

在 Node.js 中,我們使用像 Sinon 這樣的庫來實現(xiàn)(譯者注,Sinon 在測試中替換某部分代碼,減少測試項編寫的復(fù)雜度  https://sinonjs.org)。

14. 為什么在 express 中分離“應(yīng)用程序”和“服務(wù)器”是一種好的做法?

通過在 Express 中分離應(yīng)用程序和服務(wù)器,可以將 API  實現(xiàn)與網(wǎng)絡(luò)相關(guān)配置分開。在不執(zhí)行網(wǎng)絡(luò)調(diào)用的情況下執(zhí)行 API 測試,保證了更快的測試執(zhí)行和更好的代碼覆蓋度量。

要實現(xiàn)這種分離,應(yīng)該在單獨的文件中聲明 API 和 server,對應(yīng) app.js 和 server.js:

// app.js const express = require("express"); const app = express(); app.use("/", index); app.use("/contact", contact); app.use("/user", user); module.exports = app; // server.js const http = require("http"); const app = require("/app"); app.set('port', process.env.PORT); const httphttp = http.createServer(app);

15. 什么是 yarn 和 npm?為什么要用 yarn 代替 npm 呢?

npm 是與 Node.js 自帶的默認(rèn)包管理器,它有一個大型的公共庫和私有庫,存儲在 npm registry 的數(shù)據(jù)庫中(譯者注,官方默認(rèn)中心庫  http://registry.npmjs.org/,國內(nèi)淘寶鏡像 http://registry.npm.taobao.org/),用戶可以通過 npm  命令行訪問該數(shù)據(jù)庫。在 npm 的幫助下,用戶可以輕松管理項目中的依賴項。

yarn 也是一個包管理器,為了解決 npm 的一些缺點。yarn 依賴 npm 注冊中心為用戶提供對包訪問。yarn 底層結(jié)構(gòu)基于 npm,如果從  npm 遷移到 yarn,項目結(jié)構(gòu)和工作流不需要大改。

就像之前提到的,在某些情況下,yarn 提供了比 npm 更好的功能。與 npm 不同的是,它會緩存下載的每個包,不必重新下載。

通過校驗和驗證包的完整性來提供更好的安全性,保證在某個系統(tǒng)上運行的包在任何其他系統(tǒng)中的工作方式完全相同,這就是為什么選擇 yarn 而不是 npm  來進(jìn)行包管理。

到此,關(guān)于“常見的Node.js面試問題有哪些”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI