Promises
On this page本页内容
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 本节介绍了可以与Node.js驱动程序一起使用的Promises
that you can use with the Node.js driver to access the results of your method calls to your MongoDB cluster.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 与MongoDB集群通信的大多数驱动程序方法,如findOneAndUpdate()
and countDocuments()
, return Promise objects and already contain logic to handle the success or failure of the operation.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达到Fulfilled
或Rejected
状态时执行。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 如果您只需要处理Promise转换到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.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}`));
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达到Fulfilled
或Rejected
状态并返回。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:await
对next()
的调用,如以下代码片段所示,它将抛出以下错误:
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 该代码试图对已经返回结果并作为结果关闭的Cursor调用next()
on a Cursor that has already returned its results and closed as a result.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.await
对hasNext()
的调用,如以下示例所示,控制台将打印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());
}
}