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 可以相互嵌套,使代码看起来更好,更容易维护。