JavaScript assíncrono/aguardado

Resumo : neste tutorial, você aprenderá como escrever código assíncrono usando JavaScript   asyncawaitpalavras-chave.

Observe que para entender como funciona o async/ await, você precisa saber como funcionam as promessas .

Introdução às palavras-chave JavaScript assíncronas/aguardadas

No passado, para lidar com operações assíncronas, você costumava usar funções de retorno de chamada . No entanto, quando você aninha muitas funções de retorno de chamada, o código será mais difícil de manter. E você acaba com um problema notório conhecido como inferno de retorno de chamada.

Suponha que você precise realizar três operações assíncronas na seguinte sequência:

  1. Selecione um usuário do banco de dados.
  2. Obtenha serviços do usuário de uma API.
  3. Calcule o custo do serviço com base nos serviços do servidor. 

As funções a seguir ilustram as três tarefas. Observe que usamos a setTimeout()função para simular a operação assíncrona.

function getUser(userId, callback) {
    console.log('Get user from the database.');
    setTimeout(() => {
        callback({
            userId: userId,
            username: 'john'
        });
    }, 1000);
}

function getServices(user, callback) {
    console.log(`Get services of  ${user.username} from the API.`);
    setTimeout(() => {
        callback(['Email', 'VPN', 'CDN']);
    }, 2 * 1000);
}

function getServiceCost(services, callback) {
    console.log(`Calculate service costs of ${services}.`);
    setTimeout(() => {
        callback(services.length * 100);
    }, 3 * 1000);
}Linguagem de código:  JavaScript  ( javascript )

Veja a seguir as funções de retorno de chamada aninhadas:

getUser(100, (user) => {
    getServices(user, (services) => {
        getServiceCost(services, (cost) => {
            console.log(`The service cost is ${cost}`);
        });
    });
});Linguagem de código:  JavaScript  ( javascript )

Saída:

Get user from the database.
Get services of  john from the API.
Calculate service costs of Email,VPN,CDN.
The service cost is 300Linguagem de código:  JavaScript  ( javascript )

Para evitar esse problema de retorno de chamada, o ES6 introduziu as promessas que permitem escrever código assíncrono de maneiras mais gerenciáveis.

Primeiro, você precisa retornar a Promiseem cada função:

function getUser(userId) {
    return new Promise((resolve, reject) => {
        console.log('Get user from the database.');
        setTimeout(() => {
            resolve({
                userId: userId,
                username: 'john'
            });
        }, 1000);
    })
}

function getServices(user) {
    return new Promise((resolve, reject) => {
        console.log(`Get services of  ${user.username} from the API.`);
        setTimeout(() => {
            resolve(['Email', 'VPN', 'CDN']);
        }, 2 * 1000);
    });
}

function getServiceCost(services) {
    return new Promise((resolve, reject) => {
        console.log(`Calculate service costs of ${services}.`);
        setTimeout(() => {
            resolve(services.length * 100);
        }, 3 * 1000);
    });
}Linguagem de código:  JavaScript  ( javascript )

Então, você encadeia as promessas :

getUser(100)
    .then(getServices)
    .then(getServiceCost)
    .then(console.log);Linguagem de código:  CSS  ( css )

ES2017 introduziu as palavras-chave async/ awaitque se baseiam em promessas, permitindo que você escreva código assíncrono que se parece mais com código síncrono e é mais legível. Tecnicamente falando, o async/ awaité um açúcar sintático para promessas.

Se uma função retornar uma promessa, você poderá colocar a awaitpalavra-chave na frente da chamada da função, assim:

let result = await f();Linguagem de código:  JavaScript  ( javascript )

Eles awaitaguardarão o Promiseretorno do f()para se liquidar. A awaitpalavra-chave pode ser usada apenas dentro das asyncfunções.

O seguinte define uma asyncfunção que chama as três operações assíncronas em sequência:

async function showServiceCost() {
    let user = await getUser(100);
    let services = await getServices(user);
    let cost = await getServiceCost(services);
    console.log(`The service cost is ${cost}`);
}

showServiceCost();Linguagem de código:  JavaScript  ( javascript )

Como você pode ver, o código assíncrono agora se parece com o código síncrono.

Vamos mergulhar nas palavras-chave async/await.

A asyncpalavra-chave

A asyncpalavra-chave permite definir uma função que lida com operações assíncronas.

Para definir uma asyncfunção, você coloca a asyncpalavra-chave na frente da palavra-chave da função da seguinte forma:

async function sayHi() {
    return 'Hi';
}Linguagem de código:  JavaScript  ( javascript )

Funções assíncronas são executadas de forma assíncrona por meio do loop de eventos . Ele sempre retorna um Promise

Neste exemplo, como a sayHi()função retorna a Promise, você pode consumi-la, assim:

sayHi().then(console.log);Linguagem de código:  CSS  ( css )

Você também pode retornar explicitamente a Promiseda sayHi()função, conforme mostrado no código a seguir:

async function sayHi() {
    return Promise.resolve('Hi');
}Linguagem de código:  JavaScript  ( javascript )

O efeito é o mesmo.

Além das funções regulares, você pode usar a asyncpalavra-chave nas expressões de função:

let sayHi = async function () {
    return 'Hi';
}Linguagem de código:  JavaScript  ( javascript )

funções de seta :

let sayHi = async () => 'Hi'; Linguagem de código:  JavaScript  ( javascript )

e métodos de aulas:

class Greeter {
    async sayHi() {
        return 'Hi';
    }
}Linguagem de código:  JavaScript  ( javascript )

A awaitpalavra-chave

Você usa a awaitpalavra-chave para aguardar que um Promiseestado seja resolvido ou rejeitado. Você pode usar a awaitpalavra-chave apenas dentro de uma asyncfunção:

async function display() {
    let result = await sayHi();
    console.log(result);
}Linguagem de código:  JavaScript  ( javascript )

Neste exemplo, a palavra-chave instrui o mecanismo JavaScript a aguardar a conclusão awaitda função antes de exibir a mensagem.sayHi()

Observe que se você usar o awaitoperador fora de uma asyncfunção, receberá um erro.

Manipulação de erros

Se uma promessa for resolvida, o await promiseretorna o resultado. Porém, quando a promessa é rejeitada, await promiseocorrerá um erro como se houvesse uma throwdeclaração.

O seguinte código:

async function getUser(userId) {
     await Promise.reject(new Error('Invalid User Id'));
}Linguagem de código:  JavaScript  ( javascript )

… é o mesmo que isto:

async function getUser(userId) {
    throw new Error('Invalid User Id');
}Linguagem de código:  JavaScript  ( javascript )

No cenário real, demorará um pouco para que a promessa gere um erro.

Você pode detectar o erro usando a try...catchinstrução, da mesma forma que uma throwinstrução normal:

async function getUser(userId) {
    try {
       const user = await Promise.reject(new Error('Invalid User Id'));
    } catch(error) {
       console.log(error);
    }
}Linguagem de código:  JavaScript  ( javascript )

É possível detectar erros causados ​​por um ou mais await promise:

async function showServiceCost() {
    try {
       let user = await getUser(100);
       let services = await getServices(user);
       let cost = await getServiceCost(services);
       console.log(`The service cost is ${cost}`);
    } catch(error) {
       console.log(error);
    }
}Linguagem de código:  JavaScript  ( javascript )

Neste tutorial, você aprendeu como usar a palavra-chave JavaScript async/ awaitpara escrever código assíncrono que se parece com código síncrono.

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *