Node.js Promise 教程
在之前的教程中,您可能已经看到了用于异步事件的回调函数。但有时,当回调函数开始嵌套时,它可能会变成一场噩梦,程序会变得冗长而复杂。
什么是承诺?
在开始介绍 Promise 之前,我们先来回顾一下 Node.js 中的“回调”函数。我们在前面的章节中已经多次见过这些回调函数,所以让我们快速浏览一下其中的一个。
下面的示例显示了一个代码片段,用于连接到 MongoDB 数据库并对数据库中的某条记录执行更新操作。
- 在上面的代码中,函数(err,db)的部分被称为匿名函数或回调函数的声明。当 MongoClient 创建与 MongoDB 数据库,一旦连接操作完成,它将返回回调函数。因此从某种意义上说,连接操作发生在后台,完成后,它会调用我们的回调函数。请记住,这是 Node.js 的关键点之一,允许许多操作同时发生,因此不会阻止任何用户执行操作。
- 第二个代码块是在实际调用回调函数时执行的。回调函数只会更新我们的 MongoDB 数据库。
那么什么是 Promise?Promise 只是 Node.js 中回调函数的增强。在开发生命周期中,可能会出现需要将多个回调函数嵌套在一起的情况。在某个时间点,这可能会变得有点混乱且难以维护。简而言之,Promise 是对回调的增强,旨在缓解这些问题。
Promise 的基本语法如下所示;
var promise = doSomethingAync() promise.then(onFulfilled, onRejected)
- “doSomethingAync” 是执行某种处理的任何回调或异步函数。
- 这次,在定义回调时,有一个返回的值称为“promise”。
- 当返回一个承诺时,它可以有 2 个输出。这由“then 子句”定义。操作可以成功,由“onFulfilled”参数表示。或者它可以有错误,由“onRejected”参数表示。
请注意: 因此,promise 的关键方面是返回值。在 Node.js 中使用普通回调时,没有返回值的概念。由于有返回值,我们可以更好地控制如何定义回调函数。
在下一个主题中,我们将看到承诺的一个例子以及它们如何从回调中受益。
回调到承诺
现在让我们看一个例子,看看如何在 Node.js 应用程序中使用“promises”。为了在 Node.js 应用程序中使用 promise,必须先下载并安装“promise”模块。
然后,我们将修改我们的代码,如下所示,使用承诺更新“Employee”集合中的Employeename。
步骤1) 安装 NPM 模块
要在 Node JS 应用程序中使用 Promises,需要使用 promise 模块。要安装 promise 模块,请运行以下命令
npm 安装承诺
步骤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 函数中。它的作用是,当与数据库建立连接时,我们需要执行随后定义的代码片段。
- 最后,我们定义代码片段,将员工的 EmployeeName 从姓名“Martin”更新为“Mohan”。
注: -
如果你现在检查你的 MongoDB 数据库中,你会发现如果存在员工姓名为“Martin”的记录,它将被更新为“Mohan”。
要检查数据是否已正确插入数据库,需要执行以下命令 MongoDB
- 使用 EmployeeDB
- db.Employee.find({员工姓名:Mohan})
第一条语句确保您已连接到 EmployeeDb 数据库。第二条语句搜索员工姓名为“Mohan”的记录。
处理嵌套的承诺
在定义 Promise 时,需要注意的是,“then”方法本身返回一个 Promise。因此从某种意义上来说,Promise 可以相互嵌套或链接。
在下面的例子中,我们使用链接来定义 2 个回调函数,它们都将一条记录插入到 MongoDB 数据库。
(备注:链接是一种用于将方法的执行相互链接起来的概念。假设您的应用程序有两个方法,分别称为“方法 A”和“方法 B”。并且逻辑是“方法 B”应该在“方法 A”之后调用,那么您可以以这样的方式链接执行,即“方法 B”在“方法 A”之后直接被调用。)
本例中要注意的关键一点是,通过使用嵌套承诺,代码变得更清晰、更易读、更易于维护。
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”子句,它们一个接一个地执行。在第一个 then 子句中,我们传递包含数据库连接的“db”参数。然后我们使用“db”连接的 collection 属性将记录插入“Employee”集合。“insertOne”方法用于将实际文档插入 Employee 集合。
- 然后我们使用 2nd then 子句还将另一条记录插入数据库。
如果你现在检查你的 MongoDB 数据库中,你会发现有 2 条记录插入到 MongoDB 数据库。
创建自定义承诺
可以使用名为“q”的节点模块创建自定义承诺。需要使用节点包管理器下载并安装“q”库。使用“q”库后,可以调用方法“denodeify”,这将使任何函数成为返回承诺的函数。
在下面的示例中,我们将创建一个名为“Add”的简单函数,它将添加 2 个数字。我们将此函数转换为返回承诺的函数。
完成后,我们将使用 Add 函数返回的承诺在 console.log 中显示一条消息。
让我们按照以下步骤创建自定义函数来返回承诺。
步骤1) 安装 NPM 模块
要在 Node JS 应用程序中使用“q”,需要“q”模块。要安装“q”模块,请运行以下命令
npm 安装 q
步骤2) 定义以下用于创建自定义承诺的代码。
代码说明:-
- 第一步是使用 require 关键字包含“q”库。通过使用此库,我们将能够定义任何函数来返回回调。
- 我们正在创建一个名为 Add 的函数,它将添加变量 a 和 b 中定义的 2 个数字。这些值的总和将存储在变量 c 中。
- 然后我们使用 q 库来去节点化(将任何函数转换为返回承诺的函数的方法)我们的 Add 函数或者以其他方式将我们的 Add 函数转换为返回承诺的函数。
- 我们现在调用“Add”函数,并且能够获得返回的承诺值,因为我们执行了对 Add 函数进行去节点化的步骤。
- 'then' 关键字用于指定如果函数执行成功,则在 console.log 中显示字符串“Addition function done”。
运行上述代码时,console.log中将显示输出“Addition function done”,如下所示。
结语
- 在 Node.js 中使用回调函数确实有它的缺点,有时候在开发过程中,回调函数的嵌套使用会让代码变得比较混乱,难以维护。
- 嵌套回调函数的大多数问题都可以通过使用 Promise 和生成器来缓解 的node.js
- Promise 是异步函数返回的一个值,用于指示异步函数执行的处理完成。
- 当一个异步函数需要在另一个异步函数之后调用时,Promise 可以相互嵌套,以使代码看起来更好,更易于维护