La construction async / attendent est une approche relativement nouvelle pour écrire du code asynchrone en JavaScript. Il est basé sur des promesses et, par conséquent, ne bloque pas le flux principal. L'innovation de cette conception est que grâce à elle, le code asynchrone devient similaire à synchrone et se comporte de manière similaire. Cela ouvre de grandes opportunités pour le programmeur.

Avant l'arrivée d'Async / Wait, des rappels et des promesses étaient utilisés pour développer des mécanismes de programme asynchrones. L'auteur du document, dont nous publions la traduction aujourd'hui, suggère de rappeler d'abord comment écrire du code à l'ancienne, puis, à l'aide d'un exemple réel, d'étudier l'utilisation de async / wait.
Rappels
Voici un exemple de code qui utilise des rappels (fonctions de rappel):
setTimeout(() => { console.log('This runs after 1000 milliseconds.'); }, 1000);
Lors de l'utilisation des fonctions de rappel imbriquées, il existe un problème appelé l'enfer de rappel. Voici un exemple de code simplifié pour illustrer ce problème:
asyncCallOne(() => { asyncCallTwo(() => { asyncCallThree(() => { asyncCallFour(() => { asyncCallFive(() => {
Si le code contient des structures composées de rappels imbriqués les uns dans les autres, un tel code peut être difficile à comprendre, il sera difficile à maintenir.
Promesses
Voici un exemple de code qui utilise des promesses (objets Promise):
const promiseFunction = new Promise((resolve, reject) => { const add = (a, b) => a + b; resolve(add(2, 2)); }); promiseFunction.then((response) => { console.log(response); }).catch((error) => { console.log(error); });
La fonction
promiseFunction()
de cet exemple renvoie un objet
Promise
, qui est une certaine action effectuée par la fonction. Un appel à la méthode
resolve()
indique à la promesse que son opération s'est terminée avec succès. Dans de telles constructions, la méthode de promesses
.then()
est également utilisée - avec son aide, après avoir réussi à résoudre la promesse, vous pouvez exécuter un certain rappel. La méthode
.catch()
est appelée si quelque chose s'est mal passé pendant le travail de la promesse.
Fonctions asynchrones
Les fonctions déclarées à l'aide du
async
(fonctions asynchrones) nous donnent la possibilité d'écrire du code propre et non surchargé de constructions de services, ce qui nous permet d'obtenir le même résultat que nous avons obtenu en utilisant des promesses. Il convient de noter que le
async
est essentiellement juste du «sucre syntaxique» pour les promesses.
Les fonctions asynchrones sont créées à l'aide du mot clé
async
lors de la déclaration d'une fonction. Cela ressemble à ceci:
const asyncFunction = async () => {
Les fonctions asynchrones peuvent être suspendues à l'aide du mot-clé
await
. Il ne peut être utilisé que dans des fonctions asynchrones. Il vous permet de renvoyer le résultat de la fonction asynchrone, qui sera disponible une fois qu'une telle fonction aura terminé l'exécution d'une tâche.
Comparez le fonctionnement d'une fonction asynchrone et une promesse qui retourne une chaîne:
Il est facile de voir que l'utilisation du
async
vous permet d'écrire du code asynchrone qui ressemble à synchrone. Ce code est beaucoup plus facile à utiliser.
Maintenant que nous avons couvert les éléments de base, passons à notre exemple.
Convertisseur de devises
▍ Préparation préliminaire
Ici, nous allons créer un simple, mais cognitif du point de vue de l'étude de la construction de l'application async / wait. Il s'agit d'un convertisseur de devises qui utilise des données réelles obtenues à partir des API correspondantes. Le programme accepte le montant dans une certaine devise, le code de cette devise, ainsi que le code de devise dans lequel nous voulons convertir ce montant. Après cela, le programme affiche le résultat en téléchargeant d'abord les données actuelles sur les taux de change. Le programme affiche également une liste de pays dans lesquels vous pouvez dépenser de l'argent dans la devise vers laquelle le montant spécifié est transféré.
En particulier, nous allons utiliser ici les données de deux sources d'informations asynchrones:
- Service Currencylayer.com . Sur ce site, vous devrez créer un compte gratuit et obtenir une clé pour accéder à l'API (API Access Key). De là, nous prendrons les données nécessaires à la conversion du montant d'une devise à une autre.
- Service restcountries.eu . Il peut être utilisé sans inscription. De là, nous téléchargeons des données sur l'endroit où vous pouvez utiliser la devise dans laquelle nous avons converti le montant d'argent spécifié.
Créez un nouveau répertoire et exécutez-y la commande
npm init
. Lorsque le programme nous posera une question sur le nom du package en cours de création, nous introduirons un
currency-converter
. Vous ne pouvez pas répondre à d'autres questions du programme en appuyant sur
Enter
en réponse. Après cela, installez le package Axios dans notre projet en exécutant la commande
npm install axios --save
dans son répertoire. Créez un nouveau fichier appelé
currency-converter.js
.
Commençons à écrire le code du programme en connectant Axios dans ce fichier:
const axios = require('axios');
Notre projet aura trois fonctions asynchrones. Le premier chargera les données sur les devises. Le second chargera les données du pays. Le troisième collectera ces données, les présentera sous une forme conviviale et les affichera à l'écran.
▍ La première fonction est le chargement asynchrone des données monétaires
Créons une fonction
getExchangeRate()
asynchrone qui prendra deux arguments:
fromCurrency
et
toCurrency
:
const getExchangeRate = async (fromCurrency, toCurrency) => {}
Dans cette fonction, nous devons charger des données. En utilisant la construction async / wait, vous pouvez écrire les données reçues directement dans une certaine variable ou constante. Avant d'écrire le code de cette fonction, n'oubliez pas de vous inscrire
sur le site et d'obtenir une clé d'accès API. Pour charger des données, nous avons besoin de la construction suivante:
const response = await axios.get('http://www.apilayer.net/api/live?access_key=[ API]');
Après avoir reçu la réponse du système, les données dont nous avons besoin peuvent être trouvées dans l'objet de
response.data.quotes
à
response.data.quotes
. Voici le fragment de l'objet avec les données qui nous intéressent (il est visible dans le programme comme
response.data
):
{ "success":true, "terms":"https:\/\/currencylayer.com\/terms", "privacy":"https:\/\/currencylayer.com\/privacy", "timestamp":1547891348, "source":"USD", "quotes":{ "USDAED":3.673042, "USDAFN":75.350404, "USDALL":109.203989, ... "USDZWL":322.355011 } }
Placez l'objet avec des taux de change dans la constante de
rate
:
const rate = response.data.quotes;
Le code de devise de base se trouve sur
response.data.source
. Nous écrivons le code de la devise de base dans la devise de base constante:
const baseCurrency = response.data.source;
Étant donné que par défaut, les données renvoyées par cette API sont le taux de change par rapport au dollar américain (USD), créez un
usd
constant, dans lequel nous écrivons le résultat de la division de 1 par le taux de change dans lequel le montant est spécifié:
const usd = 1 / rate[`${baseCurrency}${fromCurrency}`];
Faites attention à la façon dont la clé est formée, selon laquelle nous obtenons la valeur du cours. Dans l'objet obtenu à partir de l'API, dont le fragment est donné ci-dessus, les clés sont des chaînes commençant par
USD
et se terminant par le code de la devise correspondante. Comme il est supposé que notre programme accepte les codes de devise de chaîne, nous générons une clé en concaténant une chaîne contenant le code de devise de base et ce qui est transmis à la fonction dans le paramètre
fromCurrency
.
Maintenant, afin d'obtenir le taux de change de la
fromCurrency
à la
toCurrence
, nous multiplions les
usd
constants par le taux de la
toCurrency
. Cela ressemble à ceci:
const exchangeRate = usd * rate[`${baseCurrency}${toCurrency}`];
En conséquence, nous retournerons ce qui entre dans
exchangeRate
. Voici à quoi ressemble son code complet:
const getExchangeRate = async (fromCurrency, toCurrency) => { try { const response = await axios.get('http://www.apilayer.net/api/live?access_key=[ API]'); const rate = response.data.quotes; const baseCurrency = response.data.source; const usd = 1 / rate[`${baseCurrency}${fromCurrency}`]; const exchangeRate = usd * rate[`${baseCurrency}${toCurrency}`]; return exchangeRate; } catch (error) { throw new Error(`Unable to get currency ${fromCurrency} and ${toCurrency}`); } };
Veuillez noter que la construction try / catch régulière est utilisée pour gérer les erreurs qui peuvent se produire lors de l'exécution de la requête.
▍ La deuxième fonction est le chargement asynchrone des données pays
Notre deuxième fonction,
getCountries()
, qui charge de manière asynchrone des informations sur les pays dans lesquels vous pouvez utiliser la devise dans laquelle nous convertirons le montant spécifié dans une autre devise, prendra l'argument
currencyCode
:
const getCountries = async (currencyCode) => {}
Pour charger des données, nous utilisons la commande suivante:
const response = await axios.get(`https://restcountries.eu/rest/v2/currency/${currencyCode}`);
Si, par exemple, nous utilisons le code
HRK
(kuna croate) dans la demande, nous recevrons un code JSON en réponse, dont un fragment est illustré ci-dessous:
[ { "name":"Croatia", ... } ]
Il s'agit d'un tableau d'objets contenant des informations sur les pays. Les propriétés de
name
de ces objets contiennent le nom du pays. Vous pouvez accéder à ce tableau à l'aide de la construction
response.data
. Nous appliquons la méthode du tableau
map()
pour extraire les noms des pays des données reçues et renvoyer ces données de la fonction
getCountries()
, qui sera un tableau de noms de pays:
return response.data.map(country => country.name);
Voici le
getCountries()
complet de la fonction
getCountries()
:
const getCountries = async (currencyCode) => { try { const response = await axios.get(`https://restcountries.eu/rest/v2/currency/${currencyCode}`); return response.data.map(country => country.name); } catch (error) { throw new Error(`Unable to get countries that use ${currencyCode}`); } };
▍Troisième fonction - collecte et sortie des données
Notre troisième fonction asynchrone,
convertCurrency ()
, acceptera les arguments
fromCurrency
,
toCurrency
et
amount
- codes de devise et montant.
const convertCurrency = async (fromCurrency, toCurrency, amount) => {}
Dans ce document, nous obtenons d'abord le taux de change:
const exchangeRate = await getExchangeRate(fromCurrency, toCurrency);
Ensuite, nous chargeons la liste des pays:
const countries = await getCountries(toCurrency);
Ensuite, nous effectuons la conversion:
const convertedAmount = (amount * exchangeRate).toFixed(2);
Et après que toutes les données nécessaires ont été collectées, nous renvoyons la ligne que l'utilisateur du programme verra:
return `${amount} ${fromCurrency} is worth ${convertedAmount} ${toCurrency}. You can spend these in the following countries: ${countries}`;
Voici le code de fonction complet:
const convertCurrency = async (fromCurrency, toCurrency, amount) => { const exchangeRate = await getExchangeRate(fromCurrency, toCurrency); const countries = await getCountries(toCurrency); const convertedAmount = (amount * exchangeRate).toFixed(2); return `${amount} ${fromCurrency} is worth ${convertedAmount} ${toCurrency}. You can spend these in the following countries: ${countries}`; };
Veuillez noter que cette fonction n'a pas de bloc try / catch, car elle ne fonctionne qu'avec les résultats qui lui sont fournis par les deux fonctions décrites précédemment.
▍Démarrez le programme
Nous avons préparé trois fonctions, dont deux chargent les données de divers services, et l'une recueille ces données et prépare la sortie. Il nous suffit maintenant d'appeler cette fonction, en lui passant tout ce dont nous avons besoin. Nous n'implémenterons pas ici de mécanismes qui permettent d'appeler notre programme à partir de la ligne de commande avec le transfert des devises et des codes de somme, bien que vous puissiez le faire si vous le souhaitez. Nous appelons simplement la fonction
convertCurrency()
, en lui passant les données nécessaires:
convertCurrency('EUR', 'HRK', 20) .then((message) => { console.log(message); }).catch((error) => { console.log(error.message); });
Ici, nous voulons savoir combien de kuna croate peut être échangé contre 20 euros et en cours de route pour savoir dans quels pays cet argent peut être dépensé.
Nous appelons le programme en entrant la commande suivante dans le terminal:
node currency-converter.js
En réponse, nous obtenons les informations suivantes.
Le résultat du programmeIci, juste au cas où, le code complet de notre projet.
const axios = require('axios'); const getExchangeRate = async (fromCurrency, toCurrency) => { try { const response = await axios.get('http://www.apilayer.net/api/live?access_key=[ API]'); const rate = response.data.quotes; const baseCurrency = response.data.source; const usd = 1 / rate[`${baseCurrency}${fromCurrency}`]; const exchangeRate = usd * rate[`${baseCurrency}${toCurrency}`]; return exchangeRate; } catch (error) { throw new Error(`Unable to get currency ${fromCurrency} and ${toCurrency}`); } }; const getCountries = async (currencyCode) => { try { const response = await axios.get(`https://restcountries.eu/rest/v2/currency/${currencyCode}`); return response.data.map(country => country.name); } catch (error) { throw new Error(`Unable to get countries that use ${currencyCode}`); } }; const convertCurrency = async (fromCurrency, toCurrency, amount) => { const exchangeRate = await getExchangeRate(fromCurrency, toCurrency); const countries = await getCountries(toCurrency); const convertedAmount = (amount * exchangeRate).toFixed(2); return `${amount} ${fromCurrency} is worth ${convertedAmount} ${toCurrency}. You can spend these in the following countries: ${countries}`; }; convertCurrency('EUR', 'HRK', 20) .then((message) => { console.log(message); }).catch((error) => { console.log(error.message); });
Résumé
Nous espérons que cet exemple d'utilisation de la construction async / attendent dans des conditions réelles a aidé ceux qui ne comprenaient pas cette construction avant de le comprendre.
Chers lecteurs! Si vous utilisez la construction async / wait en pratique, veuillez partager vos impressions à ce sujet.