譯:使用頻率最高的前30個Nodejs面試問題 の 11-20

做者 • Dhanjiv Pandey • 本文出處 • 已得到中譯受權
做者twitter
譯者主頁javascript

譯者按: 2018年的文章,其中部分問題放在今天仍然不算過期。

# Q-11:什麼是回調地獄?

一開始,你能夠在瞭解回調後表揚它。回調地獄是大量嵌套的回調,這使得代碼難以閱讀和維護。html

讓咱們看看下面的代碼示例:java

downloadPhoto('http://coolcats.com/cat.gif', displayPhoto)
function displayPhoto (error, photo) {
  if (error) console.error('Download error!', error)
  else console.log('Download finished', photo)
}
console.log('Download started')

在這種狀況下,Node.js首先聲明 displayPhoto 函數。此後,它將調用 downloadPhoto 函數並傳遞 displayPhoto 函數做爲其回調。最後,該代碼在控制檯上顯示Download started 。僅在 downloadPhoto 完成其全部任務的執行後,纔會執行 displayPhotonode

# Q-12:如何避免在Node.js出現回調地獄?

Node.js在內部使用單線程事件循環來處理排隊的事件。可是,若是任務的運行時間比預期的長,則此方法可能致使阻塞整個過程。web

Node.js經過合併回調(也稱爲higher-order函數)解決了此問題。所以,只要長時間運行的進程完成執行,就會觸發關聯的回調。經過這種方法,它能夠容許代碼在長時間運行的任務以後繼續執行。express

然而,上述解決方案看起來很是有前途。可是有時候,這可能會致使複雜且沒法讀取的代碼。更多的狀況下它會致使返回的回調鏈將更長。npm

因爲這種史無前例的複雜性,調試代碼很是困難,可能會耗費大量時間。有四種解決方案能夠解決回調地獄問題。segmentfault

1. 程序模塊化.
它建議將邏輯分爲較小的模塊。而後從主模塊將它們鏈接在一塊兒以達到所需的結果。promise

2. 使用 async 機制.
它是一個普遍使用的Node.js模塊,提供了一個連續的執行流。
異步模塊具備 async.waterfall API,該API使用下一個回調將數據從一個操做傳遞到另外一操做。瀏覽器

另外一個異步API async.map 容許並行遍歷項目列表,並使用另外一個結果列表進行回調。

使用異步方法,調用者的回調僅被調用一次。這裏的調用者是使用async模塊的主方法。

3. 使用 promises 機制.
Promises 提供了另外一種編寫異步代碼的方法. 它們要麼返回執行結果,要麼返回 error/exception.實現promise須要使用 then() 函數,該函數等待 promise 對象返回。它帶有兩個可選參數,是兩個函數。根據promise的狀態,只有一個會被調用。若是promise獲得實現,則將執行第一個函數調用。可是,若是Promise被拒絕,則將調用第二個函數。

4. 使用 generators.
Generators是輕量級的routines,它們經過yield關鍵字使函數等待並恢復。生成器函數使用特殊語法function* ()。他們還可使用諸如promises或thunks之類的結構來暫停和恢復異步操做,並將同步代碼轉換爲異步代碼。

# Q-13:你能用Nodejs建立HTTP服務器嗎,解釋一下你使用的代碼?

是的,咱們能夠在Node.js中建立HTTP Server。咱們可使用http-server命令來執行此操做。

如下是示例代碼:

var http = require('http');
var requestListener = function (request, response) {
  response.writeHead(200, {'Content-Type': 'text/plain'});
  response.end('Welcome Viewers\n');
}
var server = http.createServer(requestListener);
server.listen(8080); // The port where you want to start with.

# Q-14:Nodejs、AJAX和jQuery之間的區別是什麼?

Node.js,AJAX和jQuery之間的一個共同特徵是它們都是JavaScript的高級實現。可是,它們的用途徹底不一樣。

Node.js –
它是用於開發客戶端服務器應用程序的服務器端平臺。例如,若是咱們必須構建一個在線員工管理系統,那麼咱們就不會使用客戶端JS來實現它。可是Node.js固然能夠作到這一點,由於它運行在相似於Apache的服務器上,而不是運行在瀏覽器上。

AJAX (aka Asynchronous Javascript and XML) –
它是一種客戶端腳本技術,主要用於呈現頁面內容而不刷新頁面。

jQuery –
它是著名的JavaScript模塊,對AJAX、DOM遍歷、循環等進行了補充。這個庫提供了許多有用的函數來幫助JavaScript開發。不過,使用它不是強制性的,它還管理跨瀏覽器的兼容性,因此能夠幫助您生成高度可維護的web應用程序。

# Q-15:Node.js中的Globals是什麼?

Node.js中有三個關鍵字構成Globals。它們是 GlobalProcessBuffer

Global
Global關鍵字表示全局名稱空間對象。它充當全部其餘global對象的容器。若是咱們輸入console.log(global),它會所有打印出來。

關於全局對象要注意的重要一點是,並不是全部對象都在全局範圍內,其中一些屬於模塊範圍。所以,不使用var關鍵字聲明它們或將它們添加到Global對象是明智的。

使用var關鍵字聲明的變量在模塊中變爲局部變量,而那些沒有聲明的變量會訂閱到全局對象。

Process
它也是全局對象之一,但包含將同步功能轉換爲異步回調的其餘功能。從代碼中的任何地方訪問它都沒有限制。它是EventEmitter類的實例。每一個node application object都是Process對象的一個​​實例。

它主要返回有關應用程序或環境的信息。

  • <process.execPath> – 獲取Node應用程序的執行路徑.
  • <process.Version> – 獲取當前正在運行的Node版本.
  • <process.platform> – 獲取服務器平臺.

其餘一些有用的處理方法以下:

  • <process.memoryUsage> – 瞭解node程序使用的內存.
  • <process.NextTick> – 附加一個將在下一個循環中調用的回調函數。它會致使函數延遲執行.

Buffer
Buffer是Node.js中處理二進制數據的一個類。它相似於整數列表,可是存儲在V8堆以外的原始內存中。

咱們能夠將JavaScript字符串對象轉換爲Buffers。但這須要顯式地聲明編碼類型。

  • <ascii> – 指定7位ASCII數據.
  • <utf8> – 表示多字節編碼的Unicode字符集.
  • <utf16le> – 表示2或4個字節,用小尾數編碼的Unicode字符.
  • <base64> – 用於Base64字符串編碼.
  • <hex> – 將每一個字節編碼爲兩個十六進制字符.

這是使用Buffer類的語法:

> var buffer = new Buffer(string, [encoding]);

上面的命令將分配一個新的buffer來保存默認編碼爲 utf8 的字符串。可是,若是您想將string寫入現有的buffer object,請使用如下代碼行:

> buffer.write(string)

buffer 還提供其餘方法,例如readInt8writeUInt8,該方法容許從各類類型的數據讀/寫到 buffer。

# Q-16:如何在Node.js中加載HTML?

要在Node.js中加載HTML,咱們必須將HTML代碼中的 Content-type 從 text/plain 更改成 text/html。
讓咱們看一個在web服務器中建立靜態文件的示例:

fs.readFile(filename, "binary", function(err, file) {
  if (err) { 
    response.writeHead(500, {"Content-Type": "text/plain"});
    response.write(err + "\n");
    response.end();
    return;
  }

  response.writeHead(200);
  response.write(file, "binary");
  response.end();
});

如今,咱們將修改此代碼以加載HTML頁面而不是純文本。

fs.readFile(filename, "binary", function(err, file) {
  if (err) { 
    response.writeHead(500, {"Content-Type": "text/html"});
    response.write(err + "\n");
    response.end();
    return;
  }

  response.writeHead(200, {"Content-Type": "text/html"});
  response.write(file);
  response.end();
});

# Q-17:Node.js中的EventEmitter是什麼?

Node.js中的事件模塊容許咱們建立和處理自定義事件。事件模塊包含 EventEmitter類,可用於引起和處理自定義事件。可經過如下代碼進行訪問:

// 導入事件模塊
var events = require('events');

// 建立一個eventEmitter對象
var eventEmitter = new events.EventEmitter();

當EventEmitter實例遇到錯誤時,它將觸發 error 事件。添加新的偵聽器時,將觸發 newListener事件,而刪除偵聽器時,將觸發 removeListener事件。
EventEmitter提供多個屬性,例如 onemiton屬性用於將函數綁定到事件,emit用於觸發事件。

# Q-18:Node.js中有幾種類型的流?

Node.js中的Stream是容許以連續方式從源讀取數據或將數據寫入特定目標的對象。在Node.js中,有四種類型的流:

  • <Readable> – 這是用於讀取操做的Stream.
  • <Writable> – 它簡化了寫的操做.
  • <Duplex> – 此流可用於讀取和寫入操做.
  • <Transform> – 它是雙工流的一種形式,它根據可用的輸入執行計算.

上面討論的全部流都是 EventEmitter 類的實例。由流拋出的事件隨時間而變化。一些經常使用事件以下:

  • <data> – 當有可供讀取的數據時,將觸發此事件.
  • <end> – 沒有更多數據可讀取時,Stream將觸發此事件.
  • <error> – 當讀取或寫入數據時出現任何錯誤時觸發此事件.
  • <finish> – 當全部數據刷新到底層系統後,將觸發此事件.

# Q-19:列出並解釋重要的REPL命令?

下面是一些最經常使用的REPL命令:

  • <.help> – 顯示全部命令的幫助.
  • <tab Keys> – 它顯示全部可用命令的列表.
  • <Up/Down Keys> – 它的用途是肯定以前在REPL中執行了什麼命令.
  • <.save filename> – 將當前的REPL會話保存到文件中.
  • <.load filename> – 在當前REPL會話中加載指定的文件.
  • <ctrl + c> – 用於終止當前命令.
  • <ctrl + c (twice)> – 退出REPL.
  • <ctrl + d> – 此命令執行從REPL退出.
  • <.break> – 從多行表達式導出.
  • <.clear> – 從多行表達式退出.

# Q-20:Node.js中的NPM是什麼?

NPM 是Node的一個包管理器,也是一個平臺。它提供如下兩個主要功能:

  • 它做爲node.js包/模塊的在線存儲庫,這些包/模塊存在於<nodejs.org>(譯者:不該該是npmjs.com嗎?)中。
  • 它做爲命令行工具來安裝包,執行Node.js軟件包的版本管理和依賴關係管理。

NPM與Node.js捆綁在一塊兒安裝。咱們可使用如下命令:

# 驗證它的版本
$ npm --version

# 使用如下命令幫助安裝任何Node.js模塊。
# $ npm install <Module Name>

# 例如,下面是安裝一個著名的Node.js web框架模塊express-的命令
$ npm install express

# 未完待續 ...

相關文章
相關標籤/搜索