loading...

Dica Promise.all()

wandealves profile image Wanderson Alves Rodrigues ・3 min read

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

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

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

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

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

Posted on by:

wandealves profile

Wanderson Alves Rodrigues

@wandealves

Sou Wanderson Alves Rodrigues desenvolvedor formado pelo IFES - Instituto Federal do Espírito Santo. Esse blog tem o objetivo de compartilhar meus conhecimentos em desenvolvimento de software.

Discussion

markdown guide