Node.js Promise 教程

在之前的教程中,您已经看到过用于异步事件的回调函数。但有时回调函数在开始嵌套时会变成噩梦,程序会变得冗长而复杂。

什么是 Promise?

在我们开始学习 Promise 之前,让我们先回顾一下 Node.js 中的“回调函数”。我们在之前的章节中已经见过很多回调函数了,所以让我们快速地回顾其中一个。

下面的示例显示了一个代码片段,用于连接到 MongoDB 数据库并在数据库中的一个记录上执行更新操作。

Node.js Promise

  1. 在上面的代码中,函数(err,db)的部分被称为匿名函数或回调函数的声明。当 MongoClient 创建到 MongoDB 数据库的连接时,一旦连接操作完成,它就会将控制权返回给回调函数。所以从某种意义上说,连接操作是在后台进行的,当它完成时,它会调用我们的回调函数。请记住,这是 Node.js 的关键点之一,它允许许多操作同时进行,从而不会阻止任何用户执行操作。
  2. 第二个代码块是在回调函数实际被调用时执行的代码。回调函数只是更新我们 MongoDB 数据库中的一条记录。

那么什么是 Promise 呢?好吧,Promise 只是 Node.js 中回调函数的增强。在开发生命周期中,可能会出现需要将多个回调函数嵌套在一起的情况。这在某个时间点可能会变得混乱且难以维护。简而言之,Promise 是对回调函数的增强,旨在缓解这些问题。

Promise 的基本语法如下所示;

var promise = doSomethingAync()
promise.then(onFulfilled, onRejected)
  • “doSomethingAync”是执行某种处理的任何回调或异步函数。
  • 这次,在定义回调时,有一个称为“Promise”的返回值。
  • 当返回 Promise 时,它可以有两个输出。这由“then 子句”定义。操作可能成功,由“onFulfilled”参数表示。或者它可能有一个错误,由“onRejected”参数表示。

注意: 因此,Promise 的关键方面是返回值。在 Node.js 中处理普通回调时,没有返回值这一概念。由于返回值,我们可以更好地控制回调函数的定义方式。

在下一个主题中,我们将看到一个 Promise 的示例以及它们如何从回调中获益。

回调函数到 Promise

现在让我们看一个如何在 Node.js 应用程序中使用“Promise”的示例。为了在 Node.js 应用程序中使用 Promise,必须首先下载并安装“promise”模块。

然后,我们将像下面这样修改我们的代码,该代码使用 Promise 更新“Employee”集合中的 Employeename。

步骤 1) 安装 NPM 模块

要在 Node JS 应用程序中使用 Promise,需要 promise 模块。要安装 promise 模块,请运行以下命令

npm install promise

步骤 2) 修改代码以包含 Promise

Callbacks to Promises

var Promise = require('promise');
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb:///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”姓名的 Employee 的 EmployeeName 更新为“Mohan”。

注意:-

如果现在检查 MongoDB 数据库的内容,您会发现如果存在 EmployeeName 为“Martin”的记录,它将被更新为“Mohan”。

要检查数据是否已正确插入数据库,您需要执行以下 MongoDB 命令

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

第一个语句确保您已连接到 EmployeeDb 数据库。第二个语句搜索 EmployeeName 为“Mohan”的记录。

处理嵌套的 Promise

在定义 Promise 时,需要注意的是,“then”方法本身也返回一个 Promise。因此,从某种意义上说,Promise 可以相互嵌套或链接。

在下面的示例中,我们使用链式调用来定义 2 个回调函数,这两个函数都将一条记录插入 MongoDB 数据库。

(注意:链式调用是将方法的执行链接在一起的概念。假设您的应用程序有两个名为“methodA”和“methodB”的方法。逻辑是“methodB”应该在“methodA”之后调用,那么您将链接执行,以便“methodB”在“methodA”之后直接被调用。)

此示例的关键之处在于,通过使用嵌套的 Promise,代码变得更简洁、可读且易于维护。

Dealing with Nested Promises

var Promise = require('promise');
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb:///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"
        })
    })
});

代码解释:

  1. 我们现在定义两个“then”子句,它们按顺序执行。在第一个 then 子句中,我们传递包含数据库连接的“db”参数。然后,我们使用“db”连接的 collection 属性将记录插入“Employee”集合。使用“insertOne”方法将实际文档插入 Employee 集合。
  2. 然后,我们使用第二个 then 子句也将一条记录插入数据库。

如果现在检查 MongoDB 数据库的内容,您会发现有 2 条记录已插入 MongoDB 数据库。

创建自定义 Promise

可以通过使用名为“q”的 node 模块来创建自定义 Promise。需要使用 Node 包管理器下载并安装“q”库。在使用“q”库后,可以调用“denodeify”方法,该方法会将任何函数转换为返回 Promise 的函数。

在下面的示例中,我们将创建一个名为“Add”的简单函数,该函数将添加两个数字。我们将此函数转换为返回 Promise 的函数。

完成后,我们将使用 Add 函数返回的 Promise 在 console.log 中显示一条消息。

让我们按照以下步骤创建我们的自定义函数以返回 Promise。

步骤 1) 安装 NPM 模块

要在 Node JS 应用程序中使用“q”,需要“q”模块。要安装“q”模块,请运行以下命令

npm install q

步骤 2) 定义以下代码,用于创建自定义 Promise。

Creating a Custom Promise

代码解释:

  1. 第一部分是使用 require 关键字包含“q”库。通过使用此库,我们将能够定义任何函数以返回回调。
  2. 我们正在创建一个名为 Add 的函数,该函数将添加变量 a 和 b 中定义的两个数字。这些值的和将存储在变量 c 中。
  3. 然后,我们使用 q 库对我们的 Add 函数进行 denodeify(用于将任何函数转换为返回 Promise 的函数),或者换句话说,将我们的 Add 函数转换为返回 Promise 的函数。
  4. 我们现在调用我们的“Add”函数,并能够获得返回的 Promise 值,因为我们在前面执行了 denodeify Add 函数的步骤。
  5. 使用“then”关键字指定如果函数执行成功,则在 console.log 中显示字符串“Addition function completed”。

运行上述代码时,输出“Addition function completed”将显示在 console.log 中,如下所示。

Creating a Custom Promise

摘要

  • 在 Node.js 中使用回调函数确实存在缺点。有时在开发过程中,嵌套使用回调函数会使代码更加混乱且难以维护。
  • 使用 Promise 和生成器可以缓解嵌套回调函数的大部分问题,这些都在 node.js 中。
  • Promise 是异步函数返回的一个值,用于指示异步函数执行的处理的完成。
  • Promise 可以嵌套在彼此内部,以便在需要在一个异步函数之后调用另一个异步函数时,使代码看起来更好且更易于维护。