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" }	
		});
});
  1. 在上面的程式碼中,函式的一部分 (err,db) 被稱為匿名或回撥函式的宣告。當 MongoClient 建立與 MongoDB 資料庫的連線時,一旦連線操作完成,它將返回到回撥函式。所以從某種意義上說,連線操作發生在後臺,當它完成時,它會呼叫我們的回撥函式。請記住,這是 Node.js 的關鍵點之一,允許許多操作同時發生,因此不會阻止任何使用者執行操作。

  2. 第二個程式碼塊是實際呼叫回撥函式時執行的程式碼塊。回撥函式只更新 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"
            }
        });
    }); 

程式碼說明: -

  1. 第一部分是包含 promise 模組,它允許我們在程式碼中使用 promise 功能。
  2. 我們現在可以將 then 函式附加到 MongoClient.connect 函式中。這樣做的是,當建立與資料庫的連線時,我們需要執行此後定義的程式碼片段。
  3. 最後,我們定義了我們的程式碼片段,它執行將名為 Martin 的員工的 EmployeeName 更新為 Mohan 的工作。

注意:-

如果你現在檢查 MongoDB 資料庫的內容,你會發現如果存在 EmployeeName 為 Martin 的記錄,它將更新為 Mohan

要檢查資料是否已正確插入資料庫,你需要在 MongoDB 中執行以下命令

  1. Use EmployeeDB
  2. db.Employee.find({EmployeeName:Mohan})

第一個語句確保你連線到 EmployeeDb 資料庫。第二個語句搜尋員工名稱為 Mohan 的記錄。

處理巢狀的 promise

在定義 promises 時,需要注意 then 方法本身會返回一個 promise。所以從某種意義上說,承諾可以互相巢狀或連結。

在下面的示例中,我們使用連結來定義 2 個回撥函式,這兩個函式都將記錄插入 MongoDB 資料庫。

注意:連結是用於將方法的執行連結到彼此的概念。假設你的應用程式有 2 個方法,稱為 methodAmethodB。並且邏輯是這樣的 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");}

程式碼說明: -

  1. 第一點是使用 require 關鍵字包含 q 庫。通過使用此庫,我們將能夠定義任何函式來返回回撥。
  2. 我們正在建立一個名為 Add 的函式,它將新增在變數 a 和 b 中定義的 2 個數字。這些值的總和將儲存在變數 c 中。
  3. 然後我們使用 q 庫來對我們的 Add 函式進行 denodeify(用於將任何函式轉換為將返回 promise 的函式的方法),或者將我們的 Add 函式轉換為返回 promise 的函式。
  4. 我們現在呼叫我們的 新增 功能,並且能夠獲得返回承諾值,因為我們執行的前一步驟是對 Add 函式進行去除。
  5. 使用 then 關鍵字指定如果函式執行成功,則在 console.log 中顯示字串 Addition function completed

執行上面的程式碼時,輸​​出 Addition function completed 將顯示在 console.log 中。

摘要

  • 在 Node.js 中使用回撥函式確實有它的缺點。有時在開發過程中,巢狀使用回撥函式會使程式碼更加混亂,難以維護。
  • 通過在 Node.js 中使用 promises 和 generator,可以減輕巢狀回撥函式的大多數問題
  • Promise 是非同步函式返回的值,用於指示非同步函式執行的處理完成。
  • 當需要同時呼叫許多非同步函式時,Promise 可以相互巢狀,使程式碼看起來更好,更容易維護。