Criando um Async Generator


#JAVASCRIPT

Um generator assíncrono é semelhante a um generator sincrono em que a chamada de next() é retornada a execução do generator até atingir a palavra-chave yield. Mas no lugar de retornar true e um objeto simples, next() retorna uma promise. Você pode pensar em um generator assíncrono como uma combinação de uma async function e uma generator function. Vamos escrever um exemplo que recupera dados de arquivos json passados via URLs, usando uma generator function. Observe a palavra-chave async e o símbolo de asterisco (*) na linha 7 indicando um async generator:

const srcArr = [
    'https://henriquesilva.dev/async_js/examples/1.json',
    'https://henriquesilva.dev/async_js/examples/2.json',
    'https://henriquesilva.dev/async_js/examples/3.json',
    ];

srcArr[Symbol.asyncIterator] = async function*() { // ⇒ linha 7
    let i = 0;
    for (const url of this) {
        const response = await fetch(url);
        if (!response.ok) {
            throw new Error('Unable to retrieve URL: ' + response.status);
        }
        yield response.json();
    }
};


const iterator = srcArr[Symbol.asyncIterator]();

iterator.next().then(result => {
    console.log(result.value.firstName); // ⇒ Fatima
});

iterator.next().then(result => {
    console.log(result.value.firstName); // ⇒ Larissa
});

iterator.next().then(result => {
    console.log(result.value.firstName); // ⇒ Maria
});

Nesse generator, usamos a palavra-chave await para aguardar a conclusão da operação de busca. Tal como acontece com as generator functions síncronas, os retornos de rendimento o resultado para o chamador da função. Observe como este async generator simplifica o processo de definição do protocolo iterável assíncrono. Não é apenas mais fácil de escrever, mas também menos sujeito a erros. Na produção, você também vai querer usar catch() para lidar com erros e mensagens rejeitadas. Um programa bem projetado deve ser capaz de se recuperar de erros comuns sem encerrar o aplicativo. Você pode encadear um catch() da mesma forma que seu método irmão then(). Exemplo:

iterator.next()
.then(result => {
    console.log(result.value.firstName);
})
.catch(error => {
    console.error('Caught: ' + error.message);
});

Se ocorrer um erro, catch() será executado com o motivo da rejeição passado como seu argumento.