Node.js Promise
在之前的教程中,你將看到用於非同步事件的回撥函式。但有時回撥函式在它們開始巢狀時會成為一場噩夢,程式開始變得冗長而複雜。
在本教程中,你將學習 -
- 承諾是什麼
- 迴應承諾
- 處理巢狀承諾
- 建立自定義承諾
什麼是承諾
在我們開始使用 promises 之前,讓我們首先重新審視 Node.js 中的回撥函式。我們在前面的章節中已經看到了很多這些回撥函式,所以讓我們快速瀏覽其中一個。
下面的示例顯示了一個程式碼片段,用於連線到MongoDB資料庫並對資料庫中的一個記錄執行更新操作。
var Mongoclient = require('mongodb').Mongoclient;
var url = 'mongodb://localhost/EmployeeDB';
Mongoclient.connect(url, function(err, db) {
db.collection('Employee').updateOne (
{ "EmployeeName" : "NewEmployee" },
{
$set: { "EmployeeName": "Mohan" }
});
});
-
在上面的程式碼中,函式的一部分
(err,db)
被稱為匿名或回撥函式的宣告。當 MongoClient 建立與 MongoDB 資料庫的連線時,一旦連線操作完成,它將返回到回撥函式。所以從某種意義上說,連線操作發生在後臺,當它完成時,它會呼叫我們的回撥函式。請記住,這是 Node.js 的關鍵點之一,允許許多操作同時發生,因此不會阻止任何使用者執行操作。 -
第二個程式碼塊是實際呼叫回撥函式時執行的程式碼塊。回撥函式只更新 MongoDB 資料庫中的一條記錄。
那麼什麼是承諾呢?好吧,承諾只是對 Node.js 中回撥函式的增強。在開發生命週期中,可能存在需要將多個回撥函式巢狀在一起的例項。這可能會變得混亂,並且難以在某個時間點維持。簡而言之,承諾是對回撥的改進,旨在緩解這些問題。
承諾的基本語法如下所示;
var promise = doSomethingAync()
promise.then(onFulfilled, onRejected)
doSomethingAync
是進行某種處理的任何回撥或非同步函式。- 這次,在定義回撥時,會返回一個稱為
promise
的值。 - 當返回一個 promise 時,它可以有 2 個輸出。這由
then
子句定義。操作可以是成功,由onFulfilled
參數列示。或者它可能有一個錯誤,由onRejected
參數列示。
**注意:**因此,承諾的關鍵方面是返回值。在 Node.js 中使用正常回撥時,沒有返回值的概念。由於返回值,我們可以更好地控制如何定義回撥函式。
在下一個主題中,我們將看到一個承諾的例子以及它們如何從回撥中受益。
迴應承諾
現在讓我們看一下如何在 Node.js 應用程式中使用 promises
的示例。為了在 Node.js 應用程式中使用 promises,必須首先下載並安裝 promise
模組。
然後我們將修改我們的程式碼,如下所示,它使用 promises 更新 Employee
集合中的 Employeename。
步驟 1: 安裝 NPM 模組
要在 Node.js 應用程式中使用 Promises,需要使用 promise 模組。要安裝 promise 模組,請執行以下命令
npm install promise
步驟 2: 修改程式碼以包含承諾
var Promise = require('promise');
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost/EmployeeDB';
MongoClient.connect(url)
.then(function(err, db) {
db.collection('Employee').updateOne({
"EmployeeName": "Martin"
}, {
$set: {
"EmployeeName": "Mohan"
}
});
});
程式碼說明: -
- 第一部分是包含
promise
模組,它允許我們在程式碼中使用 promise 功能。 - 我們現在可以將
then
函式附加到 MongoClient.connect 函式中。這樣做的是,當建立與資料庫的連線時,我們需要執行此後定義的程式碼片段。 - 最後,我們定義了我們的程式碼片段,它執行將名為
Martin
的員工的 EmployeeName 更新為Mohan
的工作。
注意:-
如果你現在檢查 MongoDB 資料庫的內容,你會發現如果存在 EmployeeName 為 Martin
的記錄,它將更新為 Mohan
。
要檢查資料是否已正確插入資料庫,你需要在 MongoDB 中執行以下命令
Use EmployeeDB
db.Employee.find({EmployeeName:Mohan})
第一個語句確保你連線到 EmployeeDb 資料庫。第二個語句搜尋員工名稱為 Mohan
的記錄。
處理巢狀的 promise
在定義 promises 時,需要注意 then
方法本身會返回一個 promise。所以從某種意義上說,承諾可以互相巢狀或連結。
在下面的示例中,我們使用連結來定義 2 個回撥函式,這兩個函式都將記錄插入 MongoDB 資料庫。
(注意:連結是用於將方法的執行連結到彼此的概念。假設你的應用程式有 2 個方法,稱為 methodA
和 methodB
。並且邏輯是這樣的 methodB
應該在之後被呼叫 methodA
,那麼你將以 methodA
直接呼叫 methodB
的方式連結執行。
在這個例子中要注意的關鍵是通過使用巢狀的 promises,程式碼變得更清晰,可讀和可維護。
var Promise = require('promise');
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost/EmployeeDB';
MongoClient.connect(url)
.then(function(db) {
db.collection('Employee').insertOne({
Employeeid: 4,
EmployeeName: "NewEmployee"
})
.then(function(db1) {
db1.collection('Employee').insertOne({
Employeeid: 5,
EmployeeName: "NewEmployee1"
})
})
});
程式碼說明: -
我們現在正在定義 2 個 then
子句,這些子句一個接一個地執行。在 first then
子句中,我們傳遞包含資料庫連線的 db
引數。然後我們使用 db
連線的 collection 屬性將記錄插入 Employee
集合。 insertOne
方法用於將實際文件插入 Employee 集合。
2. 然後我們使用第二個 then
子句將另一條記錄插入資料庫。
如果現在檢查 MongoDB 資料庫的內容,你會發現插入 MongoDB 資料庫的 2 條記錄。
建立自定義承諾
可以使用名為 q
的節點模組建立自定義承諾。需要使用節點包管理器下載和安裝 q
庫。在使用 q
庫之後,可以呼叫 denodeify
方法,這將導致任何函式成為返回 promise 的函式。
在下面的例子中,我們將建立一個名為 Add
的簡單函式,它將新增 2 個數字。我們將此函式轉換為函式以返回 promise。
完成後,我們將使用 Add 函式返回的 promise 在 console.log 中顯示一條訊息。
讓我們按照以下步驟建立自定義函式以返回一個 promise。
步驟 1: 安裝 NPM 模組
要在 Node.js 應用程式中使用 q
,需要 q
模組。要安裝 q
模組,請執行以下命令
npm install q
步驟 2: 定義以下用於建立自定義承諾的程式碼。
var Q= require('q');
function Add () {
var a, b, c;
a=5; b=6;
c=a+b;
}
var Display_promiser = Q.denodeify(Add);
var promise=Add;
promise.then
{console.log("Addition function completed");}
程式碼說明: -
- 第一點是使用
require
關鍵字包含q
庫。通過使用此庫,我們將能夠定義任何函式來返回回撥。 - 我們正在建立一個名為 Add 的函式,它將新增在變數 a 和 b 中定義的 2 個數字。這些值的總和將儲存在變數 c 中。
- 然後我們使用 q 庫來對我們的 Add 函式進行 denodeify(用於將任何函式轉換為將返回 promise 的函式的方法),或者將我們的 Add 函式轉換為返回 promise 的函式。
- 我們現在呼叫我們的
新增
功能,並且能夠獲得返回承諾值,因為我們執行的前一步驟是對 Add 函式進行去除。 - 使用
then
關鍵字指定如果函式執行成功,則在 console.log 中顯示字串Addition function completed
。
執行上面的程式碼時,輸出 Addition function completed
將顯示在 console.log 中。
摘要
- 在 Node.js 中使用回撥函式確實有它的缺點。有時在開發過程中,巢狀使用回撥函式會使程式碼更加混亂,難以維護。
- 通過在 Node.js 中使用 promises 和 generator,可以減輕巢狀回撥函式的大多數問題
- Promise 是非同步函式返回的值,用於指示非同步函式執行的處理完成。
- 當需要同時呼叫許多非同步函式時,Promise 可以相互巢狀,使程式碼看起來更好,更容易維護。