Menu Docs
Página inicial do Docs
/ / /
Controlador Node.js
/

Promessas

Nesta página

  • Visão geral
  • Promessas
  • Aguardam
  • Considerações operacionais

O driver do Node.js usa a API Javascript assíncrona para se comunicar com seu cluster MongoDB.

Javascript assíncrono permite que você execute operações sem esperar que a thread de processamento fique livre. Isso ajuda a evitar que seu aplicativo pare de responder quando executa operações de longa duração. Para obter mais informações sobre Javascript assíncrono, consulte a documentação da web MDN em Javascript assíncrono.

Esta seção descreve Promises que você pode usar com o driver Node.js para acessar os resultados de suas chamadas de método para o cluster MongoDB.

Uma Promessa é um objeto retornado pela chamada de método assíncrono que permite acessar informações sobre o eventual sucesso ou fracasso da operação que ela envolve. A Promessa está no estado pendente se a operação ainda estiver em execução, Cumprido se a operação for concluída com sucesso e Rejeitado se a operação lançar uma exceção. Para obter mais informações sobre promessas e terminologia relacionada, consulte a documentação MDN sobre Promessas.

A maioria dos métodos de driver que se comunicam com o cluster MongoDB, como findOneAndUpdate() e countDocuments(), retornam objetos Promessa e já contêm lógica para lidar com o sucesso ou a falha da operação.

Você pode definir sua própria lógica que será executada quando a Promessa atingir o estado Cumprido ou Rejeitado anexando o método then(). O primeiro parâmetro de then() é o método que é chamado quando a Promessa atinge o estado Cumprido e o segundo parâmetro opcional é o método que é chamado quando atinge o estado Rejeitado. O método then() retorna uma promessa à qual você pode acrescentar mais métodos then().

Quando você anexa um ou mais métodos do then() a uma Promessa, cada chamada passa seu resultado de execução para a próxima. Esse padrão é chamado de Encadeamento de Promessas. O seguinte trecho de código mostra um exemplo de cadeia de Promessa anexando um único método 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}`),
);

Para lidar somente com transições de promessa para o estado Rejeitado, use o método catch() em vez de passar o primeiro parâmetro null para then(). O método catch() aceita um único retorno de chamada que é executado quando a Promessa transita para o estado Rejeitada.

O método catch() geralmente é anexado no final de uma cadeia de Promessa para lidar com quaisquer exceções lançadas. O seguinte trecho de código demonstra anexar um método catch() ao final de uma cadeia de Promessa.

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

Observação

Alguns métodos no driver, como find(), retornam um Cursor em vez de uma promessa. Para determinar o tipo que cada método retorna, consulte a documentação da API do Node.js.

Se você estiver usando async funções, poderá usar o operador await em uma Promessa para pausar a execução adicional até que a Promessa atinja o estado Cumprido ou Rejeitado e retorne. Como o operador await aguarda a resolução da Promessa, você pode usá-lo no lugar do encadeamento da Promessa para executar sequencialmente sua lógica. O seguinte trecho de código usa await para executar a mesma lógica que o primeiro exemplo de cadeia de Promessa.

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 obter mais informações, consulte a documentação da MDN sobre await.

Um erro comum ao usar os métodos async é esquecer de usar o operador await nas Promessas para obter o valor do resultado em vez do objeto Promessa. Considere o exemplo a seguir, no qual iteramos em um cursor usando hasNext(), o qual retorna uma Promessa que resolve para um boolean que indica se existem mais resultados, e next(), o qual retorna uma Promessa que resolve para a próxima entrada para a qual o cursor está apontando.

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

Como a chamada para hasNext() retorna uma Promise, a declaração condicional retorna true, independentemente do valor para o qual é resolvida.

Se alterarmos o código para await a chamada apenas para next() , conforme demonstrado no trecho de código a seguir, ela apresentará o seguinte erro: 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());
}
}

Enquanto hasNext() não é chamado até que o resultado de next() retorne, a chamada para hasNext() retorna uma Promessa que avalia para true em vez do valor para o qual ele resolve, semelhante ao exemplo anterior. O código tenta ligar para next() em um cursor que já devolveu seus resultados e fechou como resultado.

Se alterarmos o código para apenas await a chamada para hasNext(), conforme mostrado no exemplo a seguir, o console imprimirá os objetos Promessa em vez dos 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());
}
}

Use await antes que os métodos hasNext() e next() chamem para garantir que você está operando com os valores de retorno corretos, conforme demonstrado no seguinte código:

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

Voltar

Especifique como as operações CRUD são executadas em conjuntos de réplicas