Résumé : dans ce tutoriel, vous apprendrez à écrire du code asynchrone en utilisant les mots-clés async await de JavaScript.

Notez que pour comprendre le fonctionnement de async et await, vous devez savoir comment fonctionnent les promesses.

exemple de fonction asynchrone en Javascript

Introduction aux mots-clés JavaScript async / await


Dans le passé, pour traiter les opérations asynchrones, vous utilisiez souvent les fonctions de rappel. Cependant, lorsque vous imbriquez de nombreuses fonctions de rappel, le code devient plus difficile à maintenir. Et vous vous retrouvez avec un problème notoire connu sous le nom de "callback hell".

Si vous voulez approfondir le sujet des [object Promise], un article leurres est dédié

Supposons que vous ayez besoin d'effectuer trois opérations asynchrones dans la séquence suivante :

  • Sélectionner un utilisateur dans la base de données.
  • Obtenir les services de l'utilisateur à partir d'une API.
  • Calculer le coût du service en fonction des services du serveur.
Les fonctions suivantes illustrent ces trois tâches. Notez que nous utilisons la fonction
function getUser(userId, callback) {
    console.log('Get user from the database.');
    setTimeout(() => {
        callback({
            userId: userId,
            username: 'john'
        });
    }, 1000);
}

function getServices(user, callback) {
    console.log(`Get services of  ${user.username} from the API.`);
    setTimeout(() => {
        callback(['Email', 'VPN', 'CDN']);
    }, 2 * 1000);
}

function getServiceCost(services, callback) {
    console.log(`Calculate service costs of ${services}.`);
    setTimeout(() => {
        callback(services.length * 100);
    }, 3 * 1000);
}

La figure suivante montre les [object Promise] imbriquées :

getUser(100, (user) => {
    getServices(user, (services) => {
        getServiceCost(services, (cost) => {
            console.log(`The service cost is ${cost}`);
        });
    });
});

Sortie :

Get user from the database.
Get services of  john from the API.
Calculate service costs of Email,VPN,CDN.
The service cost is 300

Pour éviter ce problème de callback hell, ES6 a introduit les promesses qui vous permettent d'écrire du code asynchrone de manière plus gérable.

Tout d'abord, vous devez retourner une Promise dans chaque fonction :
function getUser(userId) {
    return new Promise((resolve, reject) => {
        console.log('Get user from the database.');
        setTimeout(() => {
            resolve({
                userId: userId,
                username: 'john'
            });
        }, 1000);
    })
}

function getServices(user) {
    return new Promise((resolve, reject) => {
        console.log(`Get services of  ${user.username} from the API.`);
        setTimeout(() => {
            resolve(['Email', 'VPN', 'CDN']);
        }, 2 * 1000);
    });
}

function getServiceCost(services) {
    return new Promise((resolve, reject) => {
        console.log(`Calculate service costs of ${services}.`);
        setTimeout(() => {
            resolve(services.length * 100);
        }, 3 * 1000);
    });
}

Ensuite vous pouvez chaîner les promesses

getUser(100)
    .then(getServices)
    .then(getServiceCost)
    .then(console.log);
ES2017 a introduit les mots-clés

Si une fonction renvoie une promesse, vous pouvez placer le mot-clé await devant l'appel de la fonction, comme ceci :

let result = await f();
La fonction

L'exemple suivant définit une fonction asynchrone qui appelle les trois opérations asynchrones en séquence :

async function showServiceCost() {
    let user = await getUser(100);
    let services = await getServices(user);
    let cost = await getServiceCost(services);
    console.log(`The service cost is ${cost}`);
}

showServiceCost();

Comme vous pouvez le voir, le code asynchrone ressemble maintenant au code synchrone.

Plongeons dans les mots-clés

Qu'est-ce que async en javascript ?

Le mot-cléPour définir une fonction asynchrone, vous placez le mot-clé async devant le mot-clé
async function sayHi() {
    return 'Hi';
}
Les fonctions asynchrones s'exécutent de manière asynchrone via la boucle d'événements. Elles renvoient toujours une Promise.Dans cet exemple, comme la fonction
sayHi().then(console.log);

L'effet est le même.

Outre les fonctions régulières, vous pouvez utiliser le mot-clé
// Fonction classique
let sayHi = async function () {
    return 'Hi';
}
// Fonction fléchée
let sayHi = async () => 'Hi'; 
// Méthode de classes
class Greeter {
    async sayHi() {
        return 'Hi';
    }
}

Qu'est-ce que await en javascript ?

Vous utilisez le mot-clé
async function display() {
    let result = await sayHi();
    console.log(result);
}
Dans cet exemple, le mot-cléNotez que si vous utilisez l'opérateur

Comment gérer les erreurs dans une fonction asynchrone en javascript ?

Quand on est développeur javascript freelance il est important de bien gérer les erreurs. Si une promesse se résout, la promesse await renvoie le résultat. Cependant, si la promesse est rejetée, la promesse await lancera une erreur comme s'il y avait une instruction throw.

Le code suivant :

async function getUser(userId) {
     await Promise.reject(new Error('Invalid User Id'));
}

est la même chose que :

async function getUser(userId) {
    throw new Error('Invalid User Id');
}

Dans le scénario réel, il faudra un certain temps pour que la promesse lance une erreur.

Vous pouvez attraper l'erreur en utilisant l'instruction try...catch, de la même manière qu'une instruction throw classique :

async function getUser(userId) {
    try {
       const user = await Promise.reject(new Error('Invalid User Id'));
    } catch(error) {
       console.log(error);
    }
}

Il est possible d'attraper les erreurs causées par une ou plusieurs promesses :

async function showServiceCost() {
    try {
       let user = await getUser(100);
       let services = await getServices(user);
       let cost = await getServiceCost(services);
       console.log(`The service cost is ${cost}`);
    } catch(error) {
       console.log(error);
    }
}

Dans ce tutoriel, vous avez appris à utiliser le mot-clé JavaScript async / awaitpour écrire du code asynchrone ressemblant à du code synchrone.