做者 • Dhanjiv Pandey • 本文出處 • 已得到中譯受權
• 做者twitter
• 譯者主頁javascript
譯者按: 2018年的文章,其中部分問題放在今天仍然不算過期。
一開始,你能夠在瞭解回調後表揚它。回調地獄是大量嵌套的回調,這使得代碼難以閱讀和維護。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
完成其全部任務的執行後,纔會執行 displayPhoto
。node
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
之類的結構來暫停和恢復異步操做,並將同步代碼轉換爲異步代碼。
是的,咱們能夠在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.
Node.js,AJAX和jQuery之間的一個共同特徵是它們都是JavaScript的高級實現。可是,它們的用途徹底不一樣。
Node.js –
它是用於開發客戶端服務器應用程序的服務器端平臺。例如,若是咱們必須構建一個在線員工管理系統,那麼咱們就不會使用客戶端JS來實現它。可是Node.js固然能夠作到這一點,由於它運行在相似於Apache的服務器上,而不是運行在瀏覽器上。
AJAX (aka Asynchronous Javascript and XML) –
它是一種客戶端腳本技術,主要用於呈現頁面內容而不刷新頁面。
jQuery –
它是著名的JavaScript模塊,對AJAX、DOM遍歷、循環等進行了補充。這個庫提供了許多有用的函數來幫助JavaScript開發。不過,使用它不是強制性的,它還管理跨瀏覽器的兼容性,因此能夠幫助您生成高度可維護的web應用程序。
Node.js中有三個關鍵字構成Globals。它們是 Global
,Process
和Buffer
。
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 還提供其餘方法,例如readInt8
和writeUInt8
,該方法容許從各類類型的數據讀/寫到 buffer。
要在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(); });
Node.js中的事件模塊容許咱們建立和處理自定義事件。事件模塊包含 EventEmitter
類,可用於引起和處理自定義事件。可經過如下代碼進行訪問:
// 導入事件模塊 var events = require('events'); // 建立一個eventEmitter對象 var eventEmitter = new events.EventEmitter();
當EventEmitter實例遇到錯誤時,它將觸發 error
事件。添加新的偵聽器時,將觸發 newListener
事件,而刪除偵聽器時,將觸發 removeListener
事件。
EventEmitter提供多個屬性,例如 on
和 emit
。on
屬性用於將函數綁定到事件,emit
用於觸發事件。
Node.js中的Stream是容許以連續方式從源讀取數據或將數據寫入特定目標的對象。在Node.js中,有四種類型的流:
<Readable>
– 這是用於讀取操做的Stream.<Writable>
– 它簡化了寫的操做.<Duplex>
– 此流可用於讀取和寫入操做.<Transform>
– 它是雙工流的一種形式,它根據可用的輸入執行計算.上面討論的全部流都是 EventEmitter
類的實例。由流拋出的事件隨時間而變化。一些經常使用事件以下:
<data>
– 當有可供讀取的數據時,將觸發此事件.<end>
– 沒有更多數據可讀取時,Stream將觸發此事件.<error>
– 當讀取或寫入數據時出現任何錯誤時觸發此事件.<finish>
– 當全部數據刷新到底層系統後,將觸發此事件.下面是一些最經常使用的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>
– 從多行表達式退出.NPM 是Node的一個包管理器,也是一個平臺。它提供如下兩個主要功能:
NPM與Node.js捆綁在一塊兒安裝。咱們可使用如下命令:
# 驗證它的版本 $ npm --version # 使用如下命令幫助安裝任何Node.js模塊。 # $ npm install <Module Name> # 例如,下面是安裝一個著名的Node.js web框架模塊express-的命令 $ npm install express