Blog fellyph cintra - trabalhando com promises javascript blog fellyph cintra

Trabalhando com Promises JavaScript

A um bom tempo eu queria escrever um post sobre promises JavaScript, basicamente elas permitem-nos executar chamadas funções assíncronas, um dos casos mais comuns são as chamas em uma REST API ou chamada de recursos externos.

PWAs, por exemplo, fazem o uso extensivo de promises porque o acesso a hardware pode falhar por alguma razão, permissões ou privacidade.

Promises JavaScript

Promise em português é promessa, e o seu funcionamento é literalmente o mesmo. O JavaScript se compromete em realizar uma ação, ou seja, faz uma promessa que irá executar o comando requisitado e irá alertar quando as promises javascript forem concluídas. Isso porque é um processo assíncrono e para não deixar uma aplicação totalmente congelada a promisse JavaScript é executada em paralelo.

Promises javascript são um objeto representado e uma eventual conclusão ou falha de uma operação assíncrona. Quando criamos uma promise e a executamos, anexamos uma função callback para caso de sucesso, ou uma função em caso de falha. As promises nos nossos códigos são representadas da seguinte forma:

<pre class="wp-block-syntaxhighlighter-code">createAudioFileAsync(parametrosDeConfiguracao).then(callbackDeSucesso, callbackDeFalha)</pre>Code language: HTML, XML (xml)

Muitas pessoas pesam que o método then faz parte da API de fetch, mas na realidade a fetch retorna uma promise, assim a requisição pode ser bem sucedida ou ter alguma falha e nada melhor que uma promise para resolver este problema.

Como criar uma promisse JavaScript?

Como mencionamos anteriormente, Promisse são objetos que esperam ações com sucesso e falha e a sua construção pode ocorrer da seguinte forma:

const vouPerderPeso = new Promise( function(sucess, fail) {
    const malhar = Math.floor(Math.random() * 10) - 5;
    if(malhar < 0) {
        sucess()
    } else {
        fail();
    }
});

vouPerderPeso.then(() => {
    console.log('to no shape');
}).catch(() => {
    console.log('deu ruim');
});Code language: JavaScript (javascript)

Como podemos ver na promise que criei acima, tenho um número gerado aleatoriamente para realizar uma comparação e retornar sucesso ou falha. Promises possuem vários benefícios, outro fator é a questão de tempo, as vezes o acesso a camera ou um dado na rede não tem um prazo específico, dai surge a importância das promises JavaScript.

const entregarEncomenda = ( entrega ) => {
    const tempoDeEntrega = Math.floor(Math.random() * 5);
    setTimeout( () => {
        entrega(`Entrega foi realizada em ${tempoDeEntrega * 10}min`)
    }, tempoDeEntrega * 1000)
};

const entregarProduto1 = new Promise(entregarEncomenda);
const entregarProduto2 = new Promise(entregarEncomenda);

entregarProduto1.then((result) => {
    console.log("Produto 1: ", result);
});

entregarProduto2.then((result) => {
    console.log("Produto 2: ", result);
});Code language: JavaScript (javascript)

No código acima temos duas promises que são executadas em um tempo variável. Nesse caso as promises são chamadas e a execução do código continua sem a necessidade de para a execução do código. A lógica do código é simples, imagine que temos dois entregadores e eles podem fazer entrega em simultâneo, mas podem ter tempos de entregas diferentes.

Execução das promises JavaScript no código anterior
Execução das promises JavaScript no código anterior

Como podemos ver a entrega do produto 2 pode acontecer antes do produto 1, assim temos exemplo que o nosso código continua a sua execução.

Promises podem ter uma cadeia de execução, por exemplo, vamos considerar que o mesmo entregador tem mais de um produto para entrega:

const entregarEncomenda = ( entrega ) => {
    const tempoDeEntrega = Math.floor(Math.random() * 5);
    setTimeout(() => {
        entrega(`Entrega foi realizada em ${tempoDeEntrega * 10}min`)
    }, tempoDeEntrega * 1000);
    
};

const entregador1 = new Promise(entregarEncomenda);

const produto1 = (result) => {
    console.log("Produto 1: ", result);
};

const produto2 = (result2) => {
    console.log("Produto 2: ", result2);
}

entregador1
    .then(produto1)
    .then(produto2);Code language: JavaScript (javascript)

E o resultado será o seguinte:

Blog fellyph cintra - resultado de cadeia de promises

O segundo produto será undefined, nesse caso, porque a promessa já foi comprida, assim teríamos que criar uma nova promise.

As promises JavaScript podem ter os seguintes estados:

  • pending – estado inicial, nem cumprido, nem rejeitado
  • fulfilled – significando que a operação foi concluída com sucesso.
  • rejected – significando que a operação falhou.

O estado eventual de uma promessa pending pode ser preenchido com um valor ou rejected com um motivo (erro). No nosso exemplo, uma vez que completamos a primeira execução, não tem mais um retorno da nossa promessa, porque ela já está no estado fulfilled.

Uma promise pode ter uma única falha ou uma execução bem sucedida. Não podemos ter duas falhas, por exemplo, precisamos criar uma promise em caso de falha.

Cadeia de Promises

Uma necessidade comum é a necessidade de executar uma cadeia de operações assíncronas, uma ou mais promises atreladas. Para isso criamos a cadeia da seguinte forma:

<pre class="wp-block-syntaxhighlighter-code">const promessa1 = fazAlgo()
const promessa2 = promessa1().then(callbackDeSucesso, call)</pre>Code language: JavaScript (javascript)

Fetch também permite uma lógica única para definir conceitos relacionados a HTTP como CORS e extensões HTTP. No caso anterior temos duas promessas que uma depende da execução da primeira.

Promise.all()

O método Promise.all() recebe uma cadeia de promessas como entrada e retorna uma única Promessa, assim que resolve para uma matriz dos resultados das promessas de entrada. Essa promessa retornada será cumprida quando todas as promessas de entrada forem cumpridas ou se o iterável de entrada não contiver promessas.

Nesse caso ele rejeita imediatamente após qualquer uma das promessas de entrada resultar em falha, o método é usado caso queria realizar um tratamento quando todas as promises Javascript forem executadas com sucesso.

Além do método all, Promises tem os seguintes métodos:

  • Promise.any() – Para retornar positivo quando qualquer umas das promises passadas forem completas
  • Promise.race() – Diferente de any(), o método encerra quando qualquer uma das promises for completa ou rejeitada

Fetch & Promises

Precisamos falar sobre esses dois itens por que eles estão relacionados, Fetch API permite uma interface JavaScript ter acesso e manipular partes da linha de execução HTTP, como requisições e respostas. Isto é acessado globalmente através da função fetch(), ele trabalha de forma assíncrona assim sendo uma promise.

Vídeo sobre fetch API

Com a Fetch API conseguimos trabalhar com promises em exemplos reais, mais próximos do nosso dia a dia.

fetch('http://examplo.com/usuarios.json')
  .then((response) => response.json())
  .then((data) => console.log(data));Code language: JavaScript (javascript)

Então no exemplo acima, temos a chamada de uma URL específica, depois que recebemos o dado convertemos em JSON e fazemos o o uso desse JSON no then seguinte. Isso é muito importante como sabemos a resposta pode demorar segundos, mas nossa aplicação JavaScript não fica bloqueada. Assim, com promises JavaScript conseguimos anexar eventos em eventos assíncronos e transformar a execução do nosso script multithread.

Mais conteúdo relacionado


Publicado

em

,

por

Tags:

Comentários

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *