Eu trabalhava como desenvolvedor Java e lembro pela primeira vez quando tive contato com promessas em JavaScript. Embora o conceito parecesse simples, eu ainda não conseguia entender totalmente como o Promises funcionava. Mudou quando comecei a utilizá-los em projetos e entendi os casos que eles resolviam. Então chegou o momento da AHA e tudo ficou mais claro. Com o tempo, Promises se tornou uma arma valiosa em meu cinto de ferramentas. É estranhamente satisfatório quando posso usá-los no trabalho e resolver o tratamento assíncrono entre funções.
Você provavelmente encontra Promises pela primeira vez ao buscar dados de uma API, que também é o exemplo mais comum. Recentemente, fui entrevistado e adivinhe qual foi a primeira pergunta “Você pode me dizer a diferença entre Promise e Async Await?”. Congratulo-me com isso porque considero que é um bom ponto de partida para saber melhor como o requerente compreende o funcionamento dos mecanismos. No entanto, ele ou ela usa principalmente outras bibliotecas e estruturas. Deixe-me anotar as diferenças e descrever boas práticas para lidar com erros de funções assíncronas.
Vamos começar com a pergunta inicial: “Qual é a promessa?” Promise é um espaço reservado para o valor que ainda não sabemos, mas o obteremos como resultado de computação/função assíncrona. Se a promessa der certo, obteremos o resultado. Se a promessa não der certo, a promessa retornará um erro.
Você define Promise chamando seu construtor e passando duas funções de retorno de chamada: resolve e reject.
const newPromise = new Promise((resolve, reject) => { resolve('Hello'); // reject('Error'); });
Chamamos a função resolve quando queremos resolver a Promise com sucesso. rejeitar serve para rejeitar a promessa no caso em que ocorre um erro durante a avaliação de nossa lógica.
Usamos a função integrada para obter o resultado da Promise. Possui dois retornos de chamada passados, resultado e erro. O resultado é chamado quando a Promise é resolvida com sucesso pela função resolve. Se a promessa não for resolvida, o segundo erro de função será chamado. Esta função é acionada por rejeição ou por outro erro gerado.
newPromise.then(result => { console.log(result); // Hello }, error => { console.log("There shouldn't be an error"); });
Em nosso exemplo, obteremos o resultado Olá porque resolvemos a Promessa com sucesso.
Quando a promessa é rejeitada, seu segundo retorno de chamada de erro é sempre invocado.
const newPromise1 = new Promise((resolve, reject) => { reject('An error occurred in Promise1'); }); newPromise1.then( (result) => { console.log(result); // It is not invoked }, (error) => { console.log(error); // 'An error occurred in Promise1' } );
Uma abordagem mais recomendada para maior clareza é usar o método catch integrado.
const newPromise2 = new Promise((resolve, reject) => { reject('An error occurred in Promise2'); }); newPromise2 .then((result) => { console.log(result); // It is not invoked }) .catch((error) => { console.log(error); // 'An error occurred in Promise2' });O método
catch é encadeado e fornece seu próprio retorno de chamada de erro. Ele é invocado quando a promessa é rejeitada.
Ambas as versões funcionam bem, mas o encadeamento é IMO mais legível e é útil ao usar outros métodos integrados que abordaremos mais adiante.
O resultado de uma promessa provavelmente poderia ser outra promessa. Nesse caso, podemos encadear um número arbitrário de funções then.
getJSON('categories.json') .then(categories => { console.log('Fetched categories:', categories); return getJSON(categories[0].itemsUrl); }) .then(items => { console.log('Fetched items:', items); return getJSON(items[0].detailsUrl); }) .then(details => { console.log('Fetched details:', details); }) .catch(error => { console.error('An error has occurred:', error.message); });
Em nosso exemplo, serve para restringir os resultados da pesquisa para obter dados detalhados. Cada função then também pode ter seu retorno de chamada de erro. Se nos preocuparmos apenas em capturar qualquer erro na cadeia de chamadas, podemos aproveitar a função catch. Será avaliado se alguma das promessas retornar um erro.
Às vezes queremos esperar pelos resultados de promessas mais independentes e depois agir de acordo com os resultados. Podemos usar a função integrada Promise.all se não nos importarmos com a ordem em que as promessas foram resolvidas.
Promise.all([ getJSON('categories.json'), getJSON('technology_items.json'), getJSON('science_items.json') ]) .then(results => { const categories = results[0]; const techItems = results[1]; const scienceItems = results[2]; console.log('Fetched categories:', categories); console.log('Fetched technology items:', techItems); console.log('Fetched science items:', scienceItems); // Fetch details of the first item in each category return Promise.all([ getJSON(techItems[0].detailsUrl), getJSON(scienceItems[0].detailsUrl) ]); }) .then(detailsResults => { const laptopDetails = detailsResults[0]; const physicsDetails = detailsResults[1]; console.log('Fetched laptop details:', laptopDetails); console.log('Fetched physics details:', physicsDetails); }) .catch(error => { console.error('An error has occurred:', error.message); });
Promise.all pega uma matriz de promessas e retorna uma matriz de resultados. Se uma das promessas for rejeitada, Promise.all também será rejeitado.
Outra funcionalidade integrada é Promise.race. É usado quando você tem várias funções assíncronas - Promessas - e deseja executá-las.
Promise.race([ getJSON('technology_items.json'), getJSON('science_items.json') ]) .then(result => { console.log('First resolved data:', result); }) .catch(error => { console.error('An error has occurred:', error.message); });
A execução das promessas pode levar tempos diferentes e Promise.race avalia a primeira promessa resolvida ou rejeitada do array. É usado quando não nos importamos com o pedido, mas queremos o resultado da chamada assíncrona mais rápida.
Como você pode ver, escrever Promises requer muito código padrão. Felizmente, temos o recurso nativo Async Await, que torna o uso do Promises ainda mais fácil. Marcamos uma função pela palavra async e com isso dizemos que em algum lugar do código estaremos chamando uma função assíncrona e não devemos esperar por isso. Em seguida, a função assíncrona é chamada com a palavra await.
const fetchData = async () => { try { // Fetch the categories const categories = await getJSON('categories.json'); console.log('Fetched categories:', categories); // Fetch items from the first category (Technology) const techItems = await getJSON(categories[0].itemsUrl); console.log('Fetched technology items:', techItems); // Fetch details of the first item in Technology (Laptops) const laptopDetails = await getJSON(techItems[0].detailsUrl); console.log('Fetched laptop details:', laptopDetails); } catch (error) { console.error('An error has occurred:', error.message); } }; fetchData();
Nosso fetchData é marcado como assíncrono e nos permite usar await para lidar com chamadas assíncronas dentro da função. Chamamos mais Promises e elas serão avaliadas uma após a outra.
Usamos o bloco try...catch se quisermos lidar com os erros. O erro rejeitado é então capturado no bloco catch e podemos agir sobre ele como registrar o erro.
Ambos são recursos de manipulação de JavaScript com código assíncrono. A principal diferença está na sintaxe quando Promises usa encadeamento com then e catch, mas a sintaxe async await é mais síncrona. Isso torna mais fácil a leitura. O tratamento de erros para espera assíncrona é mais direto quando aproveita o bloco try...catch. Essa é uma pergunta que você pode facilmente responder na entrevista. Durante a resposta, você pode se aprofundar na descrição de ambos e destacar essas diferenças.
Recursos promissores
Claro, você pode usar todos os recursos com espera assíncrona. Por exemplo Promise.all.
const fetchAllData = async () => { try { // Use await with Promise.all to fetch multiple JSON files in parallel const [techItems, scienceItems, laptopDetails] = await Promise.all([ getJSON('technology_items.json'), getJSON('science_items.json'), getJSON('laptops_details.json') ]); console.log('Fetched technology items:', techItems); console.log('Fetched science items:', scienceItems); console.log('Fetched laptop details:', laptopDetails); } catch (error) { console.error('An error occurred:', error.message); } };
Promessas são um recurso fundamental em JavaScript para lidar com código assíncrono. Aqui estão as principais formas de uso:
Como já foi mostrado nos exemplos acima, este é um dos casos de uso mais utilizados para Promises e você trabalha com ele diariamente.
A leitura e gravação de arquivos de forma assíncrona pode ser feita usando promessas, especialmente pelo módulo Node.js fs.promises
import * as fs from 'fs/promises'; const writeFileAsync = async (filePath, content, options = {}) => { try { await fs.writeFile(filePath, content, options); console.log(`File successfully written to ${filePath}`); } catch (error) { console.error(`Error writing file to ${filePath}:`, error.message); } }; const filePath = 'output.txt'; const fileContent = 'Hello, this is some content to write to the file!'; const fileOptions = { encoding: 'utf8', flag: 'w' }; // Optional file write options writeFileAsync(filePath, fileContent, fileOptions);
Axios é uma biblioteca com a qual você deve estar familiarizado. Axios lida com solicitações HTTP no cliente e é amplamente utilizado.
Express é uma estrutura web para Node.js. Isso facilita a criação de aplicativos da web e APIs e, quando você usa promessas com o Express, seu código permanece limpo e fácil de gerenciar.
Todos os exemplos podem ser encontrados em: https://github.com/PrincAm/promise-example
As promessas são uma parte fundamental do JavaScript, essenciais para lidar com tarefas assíncronas no desenvolvimento web. Seja buscando dados, trabalhando com arquivos ou usando bibliotecas populares como Axios e Express, você usará frequentemente promessas em seu código.
Neste artigo, exploramos o que são promessas, como definir e recuperar seus resultados e como lidar com erros de maneira eficaz. Também abordamos recursos importantes como encadeamento, Promise.all e Promise.race. Por fim, introduzimos a sintaxe async await, que oferece uma maneira mais direta de trabalhar com promessas.
Compreender esses conceitos é crucial para qualquer desenvolvedor JavaScript, pois são ferramentas nas quais você confiará diariamente.
Se você ainda não experimentou, recomendo escrever um trecho de código simples para buscar dados de uma API. Você pode começar com uma API divertida para experimentar. Além disso, todos os exemplos e trechos de código estão disponíveis neste repositório para você explorar.
Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.
Copyright© 2022 湘ICP备2022001581号-3