DEV Community

Wanderson Alves Rodrigues
Wanderson Alves Rodrigues

Posted on

3 1

Dica Promise.all()

Nesse post vou mostrar uma forma de melhorar a performance de execução de promise, vamos imaginar uma situação onde temos uma API que obtêm clientes e desse vamos obter o endereço e contatos de outra duas API distintas.

Requisitos:

  • Node v12.x
  • Visual Studio Code

Vamos a codificação, crie um pasta no seu local de preferência, mkdir [nome_da_pasta], entre na pasta cd [nome_da_pasta] e execute npm init -y. Feito isso no Visual Studio Code vamos criar o arquivo index.js. No arquivo index.js adicione código abaixo:

function obterUnicoCliente() {
  return new Promise(function resolverPromise(resolve, reject) {
    return setTimeout(() => {
      return resolve({
        id: 1,
        nome: 'João'
      })
    }, 2000);
  });
}

function obterEndereco(idCliente) {
  return new Promise(function resolverPromise(resolve, reject) {
    return setTimeout(() => {
      return resolve({
        id: 100,
        rua: 'rua dos códigos',
        numero: 10
      })
    }, 1000);
  });
}

function obterContato(idCliente) {
  return new Promise(function resolverPromise(resolve, reject) {
    return setTimeout(() => {
      return resolve({
        id: 200,
        ddd: '88',
        telefone: '9999999',
        email: 'joao@email.com'
      })
    }, 3000);
  });
}

main();

async function main() {
  console.time('tempo')

  const cliente = await obterUnicoCliente();
  const endereco = await obterEndereco(cliente.id);
  const contato = await obterContato(cliente.id);

  console.log(`
    Cliente: ${cliente.nome}
    Endereço: ${endereco.rua}, ${endereco.numero}
    Contato: (${contato.ddd}) ${contato.telefone}, ${contato.email}
  `)

  console.timeEnd('tempo');
}
Enter fullscreen mode Exit fullscreen mode

O código é bem simples, temos três funções um para obter o cliente, uma para obter endereço e outra para contato.
A função para obter endereço e contato depende de informação de terceiros, no caso id da função de obter cliente, então existe uma dependência de dados.

Ao executar o index.js com o comando node index.js temos as saídas:

node index.js 

    Cliente: João
    Endereço: rua dos códigos, 10
    Contato: (88) 9999999, joao@email.com

tempo: 6019.026ms
Enter fullscreen mode Exit fullscreen mode

Podemos observar que o tempo de execução foi de 6019.026ms convetendo para segundos 6.019s, existe uma maneira de melhorar esse tempo que se chama Promise.all().
Para maiores detalhes vou deixar o link da documentação Promise all.

Como o obter endereço e contato só dependem do cliente e são independentes ente si é uma boa pedida para usar o Promise.all().
O código refatorado pode ser visto abaixo:

function obterUnicoCliente() {
    return new Promise(function resolverPromise(resolve, reject) {
      return setTimeout(() => {
        return resolve({
          id: 1,
          nome: 'João'
        })
      }, 2000);
    });
  }

  function obterEndereco(idCliente) {
    return new Promise(function resolverPromise(resolve, reject) {
      return setTimeout(() => {
        return resolve({
          id: 100,
          rua: 'rua dos códigos',
          numero: 10
        })
      }, 1000);
    });
  }

  function obterContato(idCliente) {
    return new Promise(function resolverPromise(resolve, reject) {
      return setTimeout(() => {
        return resolve({
          id: 200,
          ddd: '88',
          telefone: '9999999',
          email: 'joao@email.com'
        })
      }, 3000);
    });
  }

  main();

  async function main() {
    console.time('tempo')

    const cliente = await obterUnicoCliente();
    //Cometado, vamos usar agora Promise.all()
    // const endereco = await obterEndereco(cliente.id);
    // const contato = await obterContato(cliente.id);

    const resultado = await Promise.all([
      obterEndereco(cliente.id),
      obterContato(cliente.id)
    ]);

    const endereco = resultado[0];
    const contato = resultado[1];

    console.log(`
      Cliente: ${cliente.nome}
      Endereço: ${endereco.rua}, ${endereco.numero}
      Contato: (${contato.ddd}) ${contato.telefone}, ${contato.email}
    `)

    console.timeEnd('tempo');
  }
Enter fullscreen mode Exit fullscreen mode

Foi retirado a chamada individual para cada função por uma chamada usando Promise.all, que recebe um objeto iterável nesse caso usamos um array.

O tempo de execução agora ficou 5016.386ms convetendo para segundo 5.0164s,a diferença de tempo da primeira execução com a segunda foi de 1.0026 segundos, bem considerável esse ganho agora imagine em um sistema com muitas chamadas o quanto poderíamos ganhar.

$ node index.js 

    Cliente: João
    Endereço: rua dos códigos, 10
    Contato: (88) 9999999, joao@email.com

tempo: 5016.386ms
Enter fullscreen mode Exit fullscreen mode

Essa foi a dica de como podemos melhorar a performance de chamadas assíncronas usando promises, o link do projeto completo segue no link: GitHub

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs