Dica Promise.all()
Tags: javascript, node
Published: 2020-09-06 15:36:04

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:

```javascript
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:

```javascript
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**](https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/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:
```javascript
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.

```javascript
$ 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](https://github.com/wandealves/exemplopromiseall)