15 個常見的 Node.js 面試問題及答案

2021-02-21 InfoQ

作者 | Juan Cruz Martinez

譯者 | 吳留坡

策劃 | 田曉旭

臨陣磨槍,不快也光。對於成功的編程面試來說,準備和知識面一樣重要。準備使你有信心參加面試,而不用擔心莫名的緊張情緒。如果第一次參加編程面試,這一點尤其重要。

為幫助 Node.js 開發人員更好的面試,我列出了 15 個常見的 Node.js 和網絡開發相關的面試問題。

在本文中,我們將重點討論 Node.js 相關問題。但是,請記住 JavaScript 問題在 Node.js 面試中也經常問到,所以準備一些對你來說沒什麼壞處。不久前我們寫了一篇關於常見 JavaScript 面試問題的帖子,涵蓋了所有這些基礎。

https://livecodestream.dev/post/20-common-javascript-interview-questions/

現在,讓我們深入了解面試中可能會問到的 Node.js 問題。

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

Node.js 是異步的、事件驅動的、非阻塞的和單線程的,使得它成為開發下面應用程式的完美候選:

然而,Node.js 的特性使得它對於其他類型的應用程式來說不是一個理想的選擇。執行 CPU 密集型任務的應用程式(如複雜的數學計算)在使用 CPU 時表現不佳,因為 Node.js 是單線程的。

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

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

所有 EventEmitter 類都可以使用 eventEmitter.on() 函數將事件偵聽器附加到事件。然後一旦捕捉到這樣的事件,就會同步地逐個調用它的偵聽器。
const events = require("events");const eventEmitter = new events.EventEmitter();const eventListener = function(){  console.log("event triggered");}eventEmitter.on("emitted", eventListener);eventEmitter.emit("emitted");

單線程的 Node.js 必須是非阻塞的,以防止線程阻塞在需要很長時間才能完成的任務上,事件循環負責實現這種非阻塞行為,它使用應用程式線程調度掛起的任務。

Node.js 在任務完成時通過回調來處理異步函數返回的響應。與創建任務的事件類似,任務完成後也會發出一個事件。Node.js 將需要處理的事件添加到事件隊列。

事件循環對事件隊列中的事件進行迭代,並安排何時執行其關聯的回調函數。

Stream 流是從源讀取或寫入數據並將其傳輸到連續流目標的管道。有四種類型:

每個流也是一個 EventEmitter。這意味著流對象可以在流上沒有數據、流上有可用數據或流中的數據在程序刷新時發出事件。
const fs = require("fs");const readableStream = fs.createReadStream("test.txt");let content = "";readableStream.on("data", (chunk) => {  content += chunk;});readableStream.on("end", () => {  console.log(content);});

6readFile 和 createReadStream 函數有什麼區別?

readFile 函數異步讀取文件的全部內容,並存儲在內存中,然後再傳遞給用戶。

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

與 readFile 相比,createReadStream 使用更少的內存和更快的速度來優化文件讀取操作。如果文件相當大,用戶不必等待很長時間直到讀取整個內容,因為讀取時會先向用戶發送小塊內容。
const fs = require("fs");fs.readFile("test.txt", (err, content) => {  console.log(content);});

我們可以在進程級別捕獲應用程式中未捕獲的異常。為此將偵聽器附加到 process 全局對象:
process.on("uncaughtException", (err) => {  console.log("exception caught: ", err);});

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

但是 Node.js 的核心模塊之一 Cluster 支持 Node.js 應用程式開啟多核,允許我們創建多個工作進程,這些進程可以在多個內核上並行運行,並共享一個埠來偵聽事件。

每個進程使用 IPC 與主線程通信,並根據需要將伺服器句柄傳遞給其他進程。主進程可以偵聽埠本身並以循環方式將每個新連接傳遞給子進程,也可以將埠分配給子進程以便子進程偵聽請求。

反應堆設計模式是,Node.js 將回調函數(處理程序)附加到每個 I/O 操作,然後創建請求時將處理程序提交給解復用器。

解復用器收集應用程式中發出的每個 I/O 請求,並將它們作為隊列中的事件進行排隊。這個隊列就是我們所說的事件隊列。將事件排隊後,解復用器返回應用程式線程的控制。

同時,事件循環遍歷事件隊列中的每個事件,並調用附加的回調來處理事件響應。

這就是 Node.js 中所使用的反應堆模式。

儘管 Node.js 是單線程的,但是大多數用於後端開發的程式語言都提供多線程來處理應用程式操作。

為什麼單線程有利於後端開發?

REPL 代表 Read Eval Print Loop,是一個虛擬環境,可以在其中輕鬆地運行程式語言。Node.js 帶有一個內置的 REPL 來運行 JavaScript 代碼,類似於我們在瀏覽器中用來運行 JavaScript 代碼的控制臺。

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

12process.nextTick 和 setImmediate 有什麼區別?

傳遞給 setImmediate 函數的回調將在事件隊列上的下一次迭代中執行。

另一方面,回調傳遞給 process.nextTick 在下一次迭代之前以及程序中當前運行的操作完成之後執行。在應用程式啟動時,開始遍歷事件隊列之前調用它的回調。

因此,回調 process.nextTick 總是在 setImmediate 之前調用。

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

測試應用程式時使用 stub,模擬給定組件或模塊的行為,你可以將精力集中在要測試的代碼部分。通過使用 stub 代替與測試無關的組件,不必擔心外部組件會影響結果。

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

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

14為什麼在 express 中分離「應用程式」和「伺服器」是一種好的做法?

通過在 Express 中分離應用程式和伺服器,可以將 API 實現與網絡相關配置分開。在不執行網絡調用的情況下執行 API 測試,保證了更快的測試執行和更好的代碼覆蓋度量。

要實現這種分離,應該在單獨的文件中聲明 API 和 server,對應 app.js 和 server.js:
const express = require("express");const app = express();app.use("/", index);app.use("/contact", contact);app.use("/user", user);module.exports = app;const http = require("http");const app = require("/app");app.set('port', process.env.PORT);const http = http.createServer(app);

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

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

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

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

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

在本文中,討論了 15 個最常見的 Node.js 面試問題,幫助你為下一次面試做準備。知道你可能被問到的問題和答案,面試就不再緊張了。

祝你好運,面試成功!

相關焦點

  • Node.js模塊化你所需要知道的事
    : 了解這五個步驟有助於我們了解Node.js模塊化的基本原理,也能讓我們甄別一些陷阱,讓我們簡單概括下這五個步驟都做了什麼:Resolving: 找到待引用的目標模塊,並生成絕對路徑。_resolveFilename (module.js:470:15) at Function.Module.
  • Node.JS快速入門
    -v會顯示當前node的版本號2.快速入門2.1 控制臺輸出我們現在做個最簡單的小例子,演示如何在控制臺輸出,在e盤創建文件夾nodedemo ,創建文本文件demo1.js,代碼內容我們在命令提示符下輸入命令node demo1.js ,結果如下:2.2 使用函數我們剛才的例子非常簡單,咱們這裡再看一下函數的使用:我們在命令提示符下輸入命令node demo2.js ,結果如下:
  • nodejs 中文分詞模塊 node-segment
    github:https://github.com/leizongmin/node-segment 在線演示地址:http://segment.ucdok.com/ 本分詞模塊具有以下特點: 1、使用方法 安裝:$ npm install segment --save 使用:
  • Node.js 15 正式發布,14 將支持到 2023 年
    JavaScript 運行時 Node.js 已經更新到了 15 版本。
  • 復盤node項目中遇到的13+常見問題和解決方案
    本文轉載自【微信公眾號:趣談前端,ID:beautifulFront】經微信公眾號授權轉載,如需轉載與原文作者聯繫筆者之前陸陸續續接手過幾個nodejs項目, 也參與過幾個有點意思的nodejs開源項目, 最近把其中遇到的一些問題和解決方案做一個梳理, 避免大家繼續踩坑.
  • node.js、MongoDB下一代的LAMP
    node.js、MongoDB下一代的LAMP 我們大部分人在做網站時,都用的是LAMP,殊不知LAMP已成過去式,新一代的小生:nix、node.js、MongoDB誕生了,讓我們走進他們,知道他們的故事!
  • 最新Node.js框架:Koa 2 實用入門
    本文主要koa 2的文檔解讀和runkoa介紹,讓大家對koa 2有一個更簡單直接的理解Koa 2實用入門koa2已發布了一段時間,可以考慮入手,參見Node.js最新Web技術棧(2016年4月) http://nodeonly.com/stack/本文主要是koa 2的文檔解讀和runkoa介紹,讓大家對koa 2有一個更簡單直接的理解
  • centos7編程實踐:安裝nodejs
    2、node.js的優勢2.1、Nodejs語法完全是js語法,只要你懂js基礎就可以學會Nodejs後端開發Node打破了過去JavaScript只能在瀏覽器中運行的局面。首先讓我們來看一下現在的伺服器端語言中存在著什麼問題。在Java、PHP或者.NET等伺服器語言中,會為每一個客戶端連接創建一個新的線程。而每個線程需要耗費大約2MB內存。也就是說,理論上,一個8GB內存的伺服器可以同時連接的最大用戶數為4000個左右。要讓web應用程式支持更多的用戶,就需要增加伺服器的數量,而web應用程式的硬體成本當然就上升了。
  • 10 個最適合 Web 和 APP 開發的 NodeJS 框架
    Node.js Express 對於一個已經在使用 node.js 的開發人員來說,Express 或者」node.js express」並不是一個新鮮事。Express 框架提供了對 node.js 原生 API 的比較好的封裝,從而使開發者更加容易地使用node.js。 Express 框架提供了用來開發強壯的 web/移動應用,以及 API 的所有功能。
  • 專門針對初學者的Node.js教程
    與每次連接僅處理一個線程相比,它使你以很小的開銷來處理成千上萬個並行連接。案例二:HTTP伺服器Node內建有一個模塊,利用它可以很容易創建基本的HTTP伺服器。請看下面案例。$ node my_web_server.js現在你可能已經注意到一些不一樣的東西。你的Node.js應用並沒有退出。這是因為你創建了一個伺服器,你的Node.js應用將繼續運行,並響應請求,直到你關閉它。如果你希望它成為一個全功能的Web伺服器,你必須檢查所收到的請求,讀取合適的文件,並返回所請求的內容。
  • 使用Chrome DevTools有效調試Node.js
    答案很簡單:如果你沒有正確設置你的環境,使用調試器很不方便。為什麼console.log不是最好的選擇使用console.log來調試你的代碼通常會讓你陷入停止你的應用程式的無限循環,添加一個console.log,並重新啟動你的應用程式。
  • 我開始討厭node.js了
    寫在前面對於node,短短的幾年,我經歷了由愛到恨,這不是一個技術問題,而是一個心結。過了沒多久,我發現了node,原來js還可以寫後臺,這領我萌生了一個幼稚的想法,用js就可以橫掃天下了。現在很多前端新人還保持著這樣的想法。
  • Node.js為何在後端開發中不受重視?
    其他幾種語言我覺得沒有根本性的區別,論生態完善度,都是半斤八兩,論高並發,golang當之無愧,論語言友好度,Node.js可以排到首位。今天我們要講的主角是Node.js。平時我們在工作中,Java、golang、node.js都用來開發過後端服務,Java就不必講了,講多了容易惹事,golang寫起來確實麻煩,node.js無疑是開發最舒服的那一個。
  • 【 Node.js】你應該知道的 NPM 知識都在這!
    /lib/tsc.js')npm install 安裝的某個模塊,如果模塊在 package.json 中配置了 bin 屬性,在安裝時候會自動軟連結到 node_modules/.bin 中,舉個例子:如 mocha 源碼 配置了:{    "name":"mocha
  • 10+ 最佳的 Node.js 教程結合實例
    對於完全的Node.js初學者,  在深入挖掘本文章後續提到的學習項目之前,一步步按照airpair.com上面入門指南的要點 或 Node.js入門指南 之類的文章學習是不錯的選擇。Nodeschool.io是另一個比較好的網站,上面有著非常多的資料,可以學習基本的node.js及相關的技術。
  • nodejs windows環境下搭建
    目前,Node.js是在前端開發中十分受歡迎,它是一套用來編寫高性能網絡伺服器的JavaScript工具包,官網中介紹:Node.js 是一個基於Chrome JavaScript 運行時建立的一個平臺, 用來方便地搭建快速的 易於擴展的網絡應用; Node.js 藉助事件驅動, 非阻塞I
  • Node.js學習筆記第一天
    01-導入node模塊使用流程// node.js中將不同功能的代碼放在不同的js文件中,也叫模塊化,核心模塊會隨著安裝node.js時一併安裝// 1. /所在文件的 文件夾路徑nodejs中相對路徑: 是基於執行node命令時 終端所在的路徑如果nodejs中使用了相對路徑,就必須要在執行node命令前進入要執行文件的所在路徑,不然就會報錯所以最好不要在node中使用相對路徑,應該使用絕對路徑__dirname : 當前js所在的文件夾絕對路徑__filename : 當前js文件自身的絕對路徑path模塊: path.join(...paths:
  • Node.js 學習資料和教程(值得收藏)
    >被誤解的 Node.jsNode.js C++ addon編寫實戰系列熱門node.js模塊排行榜,方便找出你想要的模塊nodejs多線程,真正的非阻塞淺析nodejsNode.js  經驗分享SDCC講師專訪:淘寶樸靈談Node.jsNode.js的核心與紅利QCon北京2013 Node.js專題出品人樸靈專訪
  • 如何在Windows系統安裝最新版本的Node.js
    工具windows作業系統Node.js技術JavaScript在使用vue框架、react框架和angularjs框架時,隨著框架版本不斷更新,對應的Node.js版本也在不斷更新;如果版本不對應,搭建框架的項目就啟動不了。
  • 你不知道的 Npm(Node.js 進階必備好文)
    /lib/tsc.js')npm install 安裝的某個模塊,如果模塊在 package.json 中配置了 bin 屬性,在安裝時候會自動軟連結到 node_modules/.bin 中,舉個例子:如 mocha 源碼 配置了:{    "name":"mocha