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. This helps prevent your application from becoming unresponsive when executing long-running operations. 异步JavaScript允许您在不等待处理线程空闲的情况下执行操作。这有助于防止您的应用程序在执行长时间运行的操作时变得无响应。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.Promises,您可以将其与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. 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处于Pending状态,如果操作成功完成,则为Fulfilled,如果操作抛出异常,则为Rejected。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 more then() methods.then()方法返回一个Promise,您可以向其附加更多then(()方法。
When you append one or more 当你向Promise附加一个或多个then() methods to a Promise, each call passes its execution result to the next one. This pattern is called Promise chaining. The following code snippet shows an example of Promise chaining by appending a single then() method.then()方法时,每次调用都会将其执行结果传递给下一个。这种模式被称为Promise链。以下代码片段显示了通过附加单个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}`),
);
To handle only Promise transitions to the Rejected state, use the 要只处理Promise转换为Rejected状态,请使用catch() method rather than passing a null first parameter to then(). The catch() method accepts a single callback that is executed when the Promise transitions to the Rejected state.catch()方法,而不是将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链的末尾,以处理抛出的任何异常。以下代码片段演示了将catch()方法附加到Promise链的末尾。
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. To determine what type each method returns, see the Node.js API documentation.find())返回Cursor而不是Promise。要确定每个方法返回的类型,请参阅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. The following code snippet uses await to execute the same logic as the first Promise chaining example.await运算符等待Promise的解析,您可以使用它来代替Promise链来顺序执行您的逻辑。以下代码片段使用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 more 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方法时的一个常见错误是忘记在Promise上使用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 more 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. The code attempts to call next() on a Cursor that has already returned its results and closed as a result.next()的结果返回后才调用hasNext(),但调用hasNext会返回一个Promise,其计算结果为true,而不是解析为的值,与前面的示例类似。该代码试图对已经返回结果并因此关闭的游标调用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警告:此代码段打印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());
}
}