Executando verificação de segurança...
7

[Javascript] Melhore o seu uso de Promise: Promise.all x Promise.allSettled

Você sabia que é possível deixar o código abaixo 2x mais rápido?

async function buscarDados() {
    const pessoas = await buscarPessoas();
    const produtos = await buscarProdutos();
}

O código acima vai ser executado sequencialmente, primeiro o buscarPessoas() e depois o buscarProdutos(). Perceba que por ambas as funções serem promises e não são dependentes uma da outra, podemos executá-las em paralelo. Logo, podemos reescrever o código da seguinte maneira.

async function buscarDados() {
    const [pessoas, produtos] = await Promise.all([buscarPessoas(), buscarProdutos()]);
}

Com o código acima, as funções buscarPessoas() e buscarProdutos() são executadas em paralelo, melhorando bastante o tempo total de execução da função buscarDados().

Mas agora fica a pergunta: e se alguma das funções lançar uma exceção? Bem, podemos fazer o uso do bloco try/catch para capturar a exceção e fazer o tratamento desejado. Veja o código abaixo.

async function buscarDados() {
    try {
        const [pessoas, produtos] = await Promise.all([buscarPessoas(), buscarProdutos()]);
    } catch (erro) {
        tratarErro(erro);
    }
}

Tudo lindo, certo? Bem, não. Perceba que o erro vai ser capturado caso qualquer uma das funções buscarPessoas() ou buscarProdutos() lance alguma exceção, mas ambas podem lançar uma exceção e em tempos diferentes (lembre-se que estão executando em paralelo), logo apenas uma das exceções vai ser caputarada.

Para solucionar esse problema, podemos utiliza Promise.allSettled. Veja a seguir.

async function buscarDados() {
    const [pessoasResultado, produtosResultado] = await Promise.allSettled([buscarPessoas(), buscarProdutos()]);
}

Utilizando o allSettled o resultado é um objeto e dentro desse objeto vai ter a propriedade status, ao qual podemos utilizar para verificar se ocorreu algum erro ou não. Por isso o bloco try/catch foi removido.

A propriedade status pode ter um dos seguintes valores: fullfilled ou rejected. Com base nesses valores podemos realizar o tratamento da exceção para cada ocorrência.

async function buscarDados() {
    const [pessoasResultado, produtosResultado] = await Promise.allSettled([buscarPessoas(), buscarProdutos()]);

    if (pessoasResultado.status === 'rejected') {
        // tratar erro
    }
    
    if (productosResultado.status === 'rejected') {
        // tratar erro
    }
}
Carregando publicação patrocinada...
1

Incrível! Achei muito interessante sua didática pra otimização do código. Agora vem uma pergunta, como que você fez para aprender a otimizar seus códigos? Tem alguma dica que você tenha pra melhorar a codagem pra ficar mais dinâmica? Um abraço!

1

Murilo, não tem uma receita de bolo. Basicamente é ler código, tentar entender como algo foi feito. Uma boa prática é fazer um código e depois refatorar buscando otimiza-la, através de conhecimentos adquiridos estudando sobre boas práticas, padrões e assim vai. Quanto mais informações você tiver sobre algo, mais opções de soluções a sua mente vai formar. Vou dar um exemplo:

Vamos supor que você esteja fazendo um componente em Angular e está usando RXJS, logo existem vários operadores que você pode usar, aonde aparentemente vão dar o mesmo resultado. Você só saberá qual é o melhor operador para usar em seu código, caso você conheça as opções existentes. Eu recomendaria nesse caso, parar um tempo e ir ler a documentação do RXJS e buscar exemplos aplicados.

1

Uma dúvida se a função não retorna nada o que acontece com as variáveis?, e a ordem das variáveis corresponde a ordem das funções? Por exemplo o resultado da primeira função vai para a primeira variável?

1

Nesse caso, o resultado ainda vai ter a propriedade status, mas o campo value vai estar undefined. Por exemplo:
{ status: 'fulfilled', value: undefined }.

Sim, a ordem das variaveis é a ordem das funções.

0