Promises and Callbacks承诺和回扣¶
On this page
Overview概述¶
The Node.js driver uses the asynchronous Javascript API to communicate with your MongoDB cluster.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 two features of asynchronous Javascript -- 本节介绍异步Javascript的两个特性——Promises
and Callbacks
-- that you can use with the Node.js driver to access the results of your method calls to your MongoDB cluster.Promise
和Callbacks
,您可以使用Node.js驱动程序访问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. 如果操作仍在运行,则承诺处于挂起状态;如果操作成功完成,则承诺已实现;如果操作引发异常,则承诺将被拒绝。For more information on Promises and related terminology, see the MDN documentation on Promises.有关承诺和相关术语的更多信息,请参阅承诺的MDN文档。
Most driver methods that communicate with your MongoDB cluster such as 大多数与MongoDB集群通信的驱动程序方法,如findOneAndUpdate()
, countDocuments()
, and update()
return Promise objects and already contain logic to handle the success or failure of the operation.findOneAndUpdate()
、countDocuments()
和update()
都返回Promise
对象,并且已经包含处理操作成功或失败的逻辑。
You can define your own logic that executes once the Promise reaches the Fulfilled or Rejected state by appending the 通过附加then()
method. then()
方法,您可以定义自己的逻辑,该逻辑在承诺达到满足或拒绝状态时执行。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()
的第一个参数是在承诺达到满足状态时调用的方法,可选的第二个参数是在承诺达到拒绝状态时调用的方法。The then()
method returns a Promise to which you can append additional then()
methods.then()
方法返回一个承诺,您可以向该承诺附加额外的then()
方法。
When you append one or more 将一个或多个then()
methods to a Promise, each call passes its execution result to the next one. then()
方法附加到承诺时,每个调用都会将其执行结果传递给下一个。This pattern is called Promise chaining. 这种模式称为承诺连缀。The following code snippet shows an example of Promise chaining by appending a single 下面的代码片段显示了通过附加单个then()
method.then()
方法实现承诺链接的示例。
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.null
第一个参数传递给then()
,则可以使用catch()
方法,该方法接受单个回调,在承诺转换到拒绝状态时执行。
The catch()
method is often appended at the end of a Promise chain to handle any exceptions thrown. catch()
方法通常附加在承诺链的末尾,以处理抛出的任何异常。The following code snippet demonstrates appending a 下面的代码片段演示如何将catch()
method to the end of a Promise chain.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
函数,那么可以在承诺上使用await
运算符暂停进一步的执行,直到承诺达到满足或拒绝状态并返回。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
运算符等待承诺的解析,因此您可以使用它代替承诺链来顺序执行逻辑。The following code snippet uses 下面的代码段使用await
to execute the same logic as the first Promise chaining example.await
执行与第一个承诺链接示例相同的逻辑。
async function run(){
...
try {
res = await collection.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.有关更多信息,请参阅MDN上的await
文档。
Callbacks¶
A callback is a method that gets called after another method has finished executing. 回调是在另一个方法完成执行后调用的方法。This allows the enclosing method to continue to execute other commands until the original operation completes. 这允许封闭方法继续执行其他命令,直到原始操作完成。Callbacks are often used to enforce the order of processing commands.回调通常用于强制执行处理命令的顺序。
In the MongoDB Node.js driver, you can optionally declare a callback method to async operations that normally return Promises. 在MongoDB Node.js驱动程序中,您可以选择性地声明一个回调方法,用于通常返回承诺的异步操作。Once the operation completes execution, the callback method executes as shown in the following code snippet:一旦操作完成执行,回调方法将执行,如以下代码段所示:
collection.findOneAndUpdate(
{ name: "Barronette Peak" },
{ $set: { name: "Baronette Peak" } },
{},
function (error, result){
if (!error) {
console.log(`Operation completed successfully:${result.ok}`);
} else {
console.log(`An error occurred:${error}`);
}
},
);
For more information on the callback method signature for the specific driver method, see the API documentation.有关特定驱动程序方法的回调方法签名的更多信息,请参阅API文档。
If you specify a callback, the method does not return a Promise.如果指定回调,则该方法不会返回承诺。
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
方法时的一个常见错误是忘记对承诺使用await
运算符来获取结果的值,而不是承诺对象。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()
返回游标,它返回一个解决方案,该布尔值指示是否存在额外的结果,以及NEXT()
,它返回一个解决方案,该指针解析为指针指向的下一个条目。
async function run(){
...
// WARNING: this snippet may cause an infinite loop
const cursor = collection.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: MongoError: Cursor is closed
.next()
的调用,如下面的代码段所示,它将抛出以下错误:MongoError: Cursor is closed
。
async function run(){
...
// WARNING: this snippet throws a MongoError
const cursor = collection.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()
的调用会返回一个计算结果为true
的承诺,而不是它解析为的值,类似于前面的示例。The code attempts to call 代码尝试对已返回结果并因此关闭的游标调用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
对象而不是document
对象。
async function run(){
...
// WARNING: this snippet prints Promises instead of the objects they resolve to警告:此代码段打印承诺,而不是它们解析到的对象
const cursor = collection.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 = collection.find();
while (await cursor.hasNext()) {
console.log(await cursor.next());
}
}
For additional information on using Promises and Callbacks with the MongoDB Node.js driver, see this MongoDB University course video on asynchronous Javascript programming.有关在MongoDB Node.js驱动程序中使用承诺和回调的更多信息,请参阅MongoDB大学关于异步Javascript编程的课程视频。