Docs HomeNode.js

Promises

Overview概述

The Node.js driver uses the asynchronous Javascript API to communicate with your MongoDB cluster.Node.js驱动程序使用异步Javascript API与MongoDB集群进行通信。

Asynchronous Javascript allows you to execute operations without waiting for the processing thread to become free. 异步Javascript允许您在不等待处理线程空闲的情况下执行操作。This helps prevent your application from becoming unresponsive when executing long-running operations. 这有助于防止应用程序在执行长时间运行的操作时变得没有响应。For more information about asynchronous Javascript, see the MDN web documentation on Asynchronous Javascript.有关异步Javascript的更多信息,请参阅有关异步Javascript的MDN web文档。

This section describes Promises that you can use with the Node.js driver to access the results of your method calls to your MongoDB cluster.本节介绍了可以与Node.js驱动程序一起使用的Promises,以访问方法调用MongoDB集群的结果。

Promises

A Promise is an object returned by the asynchronous method call that allows you to access information on the eventual success or failure of the operation that they wrap. Promise是异步方法调用返回的对象,它允许您访问有关它们包装的操作的最终成功或失败的信息。The Promise is in the Pending state if the operation is still running, Fulfilled if the operation completed successfully, and Rejected if the operation threw an exception. 如果操作仍在运行,Promise处于挂起状态;如果操作成功完成,Promise将处于已完成状态;如果该操作引发异常,Promise则处于已拒绝状态。For more information on Promises and related terminology, see the MDN documentation on Promises.有关Promises和相关术语的更多信息,请参阅关于Promises的MDN文档。

Most driver methods that communicate with your MongoDB cluster, such as findOneAndUpdate() and countDocuments(), return Promise objects and already contain logic to handle the success or failure of the operation.与MongoDB集群通信的大多数驱动程序方法,如findOneAndUpdate()countDocuments(),都返回Promise对象,并且已经包含处理操作成功或失败的逻辑。

You can define your own logic that executes once the Promise reaches the Fulfilled or Rejected state by appending the then() method. 您可以通过附加then()方法来定义自己的逻辑,该逻辑在Promise达到FulfilledRejected状态时执行。The first parameter of then() is the method that gets called when the Promise reaches the Fulfilled state and the optional second parameter is the method that gets called when it reaches the Rejected state. then()的第一个参数是Promise达到Fulfilled状态时调用的方法,可选的第二个参数是达到Rejected状态时被调用的方法。The then() method returns a Promise to which you can append additional then() methods.then()方法返回一个Promise,您可以向其附加额外的then()方法。

When you append one or more then() methods to a Promise, each call passes its execution result to the next one. 当您将一个或多个then()方法附加到Promise时,每个调用都会将其执行结果传递给下一个调用。This pattern is called Promise chaining. 这种模式被称为Promise链接。The following code snippet shows an example of Promise chaining by appending a single then() method.下面的代码片段显示了通过附加单个then()方法进行Promise链接的示例。

collection
.updateOne({ name: "Mount McKinley" }, { $set: { meters: 6190 } })
.then(
res => console.log(`Updated ${res.result.n} documents`),
err => console.error(`Something went wrong: ${err}`),
);

If you only need to handle Promise transitions to the Rejected state, rather than passing a null first parameter to then(), you can instead use the catch() method which accepts a single callback, executed when the Promise transitions to the Rejected state.如果您只需要处理Promise转换到Rejected状态,而不是将第一个null参数传递给then(),则可以使用catch()方法,该方法接受单个回调,在Promise转换为Rejected时执行。

The catch() method is often appended at the end of a Promise chain to handle any exceptions thrown. The following code snippet demonstrates appending a catch() method to the end of a Promise chain.catch()方法通常附加在Promise链的末尾,以处理抛出的任何异常。下面的代码片段演示了在Promise链的末尾附加一个catch()方法。

deleteOne({ name: "Mount Doom" })
.then(result => {
if (result.deletedCount !== 1) {
throw "Could not find Mount Doom!";
}
return new Promise((resolve, reject) => {
...
});
})
.then(result => console.log(`Vanquished ${result.quantity} Nazgul`))
.catch(err => console.error(`Fatal error occurred: ${err}`));
Note

Certain methods in the driver such as find() return a Cursor instead of a Promise. 驱动程序中的某些方法(如find())返回的是Cursor而不是Promise。To determine what type each method returns, refer to the Node.js API documentation.要确定每个方法返回的类型,请参阅Node.js API文档

Await

If you are using async functions, you can use the await operator on a Promise to pause further execution until the Promise reaches either the Fulfilled or Rejected state and returns. 如果您使用的是async函数,您可以在Promise上使用await运算符来暂停进一步的执行,直到Promise达到FulfilledRejected状态并返回。Since the await operator waits for the resolution of the Promise, you can use it in place of Promise chaining to sequentially execute your logic. 由于await运算符等待Promise的解析,因此您可以使用它来代替Promise链接来顺序执行您的逻辑。The following code snippet uses await to execute the same logic as the first Promise chaining example.下面的代码片段使用await来执行与第一个Promise链接示例相同的逻辑。

async function run() {
...
try {
res = await myColl.updateOne(
{ name: "Mount McKinley" },
{ $set: { meters: 6190 } },
);
console.log(`Updated ${res.result.n} documents`);
} catch (err) {
console.error(`Something went wrong: ${err}`);
}
}

For additional information, see the MDN documentation on await.有关更多信息,请参阅有关await的MDN文档。

Operational Considerations操作注意事项

One common mistake when using async methods is to forget to use await operator on Promises to get the value of the result rather than the Promise object. 使用async方法时,一个常见的错误是忘记在Promises上使用await运算符来获取结果的值,而不是Promise对象。Consider the following example in which we iterate over a cursor using hasNext(), which returns a Promise that resolves to a boolean that indicates whether additional results exist, and next() which returns a Promise that resolves to the next entry the cursor is pointing to.考虑下面的例子,在这个例子中,我们使用hasNext()迭代游标,它返回一个Promise,该Promise解析为一个布尔值,该布尔值指示是否存在其他结果,next()返回一个Promise,该Promise解析为游标指向的下一个条目。

async function run() {
...
// WARNING: this snippet may cause an infinite loop警告:此代码段可能导致无限循环
const cursor = myColl.find();

while (cursor.hasNext()) {
console.log(cursor.next());
}
}

Since the call to hasNext() returns a Promise, the conditional statement returns true regardless of the value that it resolves to.由于对hasNext()的调用返回Promise,因此无论条件语句解析为什么值,它都会返回true

If we alter the code to await the call to next() only, as demonstrated in the following code snippet, it throws the following error:如果我们将代码更改为仅awaitnext()的调用,如以下代码片段所示,它将抛出以下错误: MongoError: Cursor is closed.

async function run() {
...
// WARNING: this snippet throws a MongoError警告:此片段引发MongoError
const cursor = myColl.find();

while (cursor.hasNext()) {
console.log(await cursor.next());
}
}

While hasNext() is not called until after the result of next() returns, the call to hasNext() returns a Promise which evaluates to true rather than the value it resolves to, similar to the prior example. 虽然只有在next()的结果返回后才会调用hasNext(),但对hasNext()的调用返回一个Promise,计算为true,而不是它所解析为的值,类似于前面的示例。The code attempts to call next() on a Cursor that has already returned its results and closed as a result.该代码试图对已经返回结果并作为结果关闭的Cursor调用next()

If we alter the code to only await the call to hasNext() as shown in the following example, the console prints Promise objects rather than the document objects.如果我们将代码更改为只awaithasNext()的调用,如以下示例所示,控制台将打印Promise对象,而不是文档对象。

async function run() {
...
// WARNING: this snippet prints Promises instead of the objects they resolve to警告:此代码段打印Promises,而不是它们解析到的对象
const cursor = myColl.find();

while (await cursor.hasNext()) {
console.log(cursor.next());
}
}

Use await before both the hasNext() and next() method calls to ensure that you are operating on the correct return values as demonstrated in the following code:hasNext()next()方法调用之前使用await,以确保操作正确的返回值,如以下代码所示:

async function run() {
...
const cursor = myColl.find();

while (await cursor.hasNext()) {
console.log(await cursor.next());
}
}