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