Docs Menu
Docs Home
/ /

Usar promesas con JavaScript asincrónico

El controlador Node.js utiliza la API de JavaScript asincrónica para comunicarse con su clúster MongoDB.

El JavaScript asíncrono permite ejecutar operaciones sin esperar a que el hilo de procesamiento esté libre. Esto ayuda a evitar que la aplicación deje de responder al ejecutar operaciones de larga duración. Para obtener más información sobre el JavaScript asíncrono, consulte la documentación web de MDN. JavaScript asincrónico.

Esta sección describe Promises que puede utilizar con el controlador Node.js para acceder a los resultados de sus llamadas de método a su clúster MongoDB.

Una Promesa es un objeto devuelto por la llamada a un método asíncrono que permite acceder a información sobre el éxito o fracaso de la operación que encapsula. La Promesa está en estado Pendiente si la operación sigue en ejecución, Cumplida si se completó correctamente y Rechazada si generó una excepción. Para obtener más información sobre las Promesas y la terminología relacionada, consulte la documentación de MDN sobre Promesas.

La mayoría de los métodos de controlador que se comunican con su clúster MongoDB, como findOneAndUpdate() y countDocuments(), devuelven objetos Promise y ya contienen lógica para manejar el éxito o el fracaso de la operación.

Puedes definir tu propia lógica que se ejecuta una vez que la Promesa alcanza el estado Cumplido o Rechazado añadiendo el then() método. El primer parámetro de then() es el método que se llama cuando la Promesa alcanza el estado Cumplido y el segundo parámetro opcional es el método que se llama cuando alcanza el estado Rechazado. El then() método devuelve una Promesa a la que puedes añadir más then() métodos.

Al añadir uno o más then() métodos a una Promesa, cada llamada pasa el resultado de su ejecución a la siguiente. Este patrón se denomina encadenamiento de promesas. El siguiente fragmento de código muestra un ejemplo de encadenamiento de promesas añadiendo un solo then() método.

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

Para gestionar únicamente las transiciones de Promesa al estado Rechazado, utiliza el método catch() en lugar de pasar un primer parámetro null a then(). El método catch() acepta una sola función de retorno que se ejecuta cuando la Promesa transita al estado Rechazado.

El método catch() suele añadirse al final de una cadena de promesas para gestionar cualquier excepción lanzada. El siguiente fragmento de código muestra cómo añadir un método catch() al final de una cadena de promesas.

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}`));

Nota

Algunos métodos del controlador, como, devuelven find() un en Cursor lugar de una promesa. Para determinar el tipo de retorno de cada método, consulte la documentación de la API de Node.js.

Si utiliza async funciones, puede usar el await operador en una Promesa para pausar la ejecución hasta que esta alcance el estado Cumplido o Rechazado y regrese. Dado await que el operador espera la resolución de la Promesa, puede usarlo en lugar del encadenamiento de Promesas para ejecutar la lógica secuencialmente. El siguiente fragmento de código usa await para ejecutar la misma lógica que el primer ejemplo de encadenamiento de Promesas.

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}`);
}
}

Para obtener más información, consulta la documentación de MDN sobre await.

Un error común al usar métodos async es olvidar usar el operador await en las Promesas para obtener el valor del resultado en lugar del objeto Promesa. Considere el siguiente ejemplo: iteramos sobre un cursor usando hasNext(), que devuelve una Promesa que se resuelve en un booleano que indica si existen más resultados, y next(), que devuelve una Promesa que se resuelve en la siguiente entrada a la que apunta el cursor.

async function run() {
...
// WARNING: this snippet may cause an infinite loop
const cursor = myColl.find();
while (cursor.hasNext()) {
console.log(cursor.next());
}
}

Dado que la llamada a hasNext() devuelve un Promise, la declaración condicional devuelve true independientemente del valor en el que se resuelva.

Si modificamos el código para await llamar únicamente a next(), como se muestra en el siguiente fragmento de código, se genera el siguiente error: MongoError: Cursor is closed.

async function run() {
...
// WARNING: this snippet throws a MongoError
const cursor = myColl.find();
while (cursor.hasNext()) {
console.log(await cursor.next());
}
}

Aunque hasNext() no se llama hasta después de que se devuelva el resultado de next(), la llamada a hasNext() devuelve una Promesa que evalúa a true en lugar del valor al que se resuelve, similar al ejemplo anterior. El código intenta llamar a next() en un Cursor que ya ha devuelto sus resultados y se ha cerrado como resultado.

Si modificamos el código para solo await la llamada a hasNext() como se muestra en el siguiente ejemplo, la consola imprime objetos Promise en lugar de objetos de documento.

async function run() {
...
// WARNING: this snippet prints Promises instead of the objects they resolve to
const cursor = myColl.find();
while (await cursor.hasNext()) {
console.log(cursor.next());
}
}

Utilice await antes de las llamadas al método hasNext() y next() para asegurarse de que está operando con los valores de retorno correctos como se muestra en el siguiente código:

async function run() {
...
const cursor = myColl.find();
while (await cursor.hasNext()) {
console.log(await cursor.next());
}
}

Volver

Almacene archivos grandes

En esta página