IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

incompréhension await et Promise


Sujet :

JavaScript

  1. #1
    Membre émérite
    Avatar de Daïmanu
    Homme Profil pro
    Développeur touche à tout
    Inscrit en
    Janvier 2011
    Messages
    705
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur touche à tout

    Informations forums :
    Inscription : Janvier 2011
    Messages : 705
    Points : 2 475
    Points
    2 475
    Par défaut incompréhension await et Promise
    Bonjour.

    Je travaille sur un bot Discord avec discord.js, et ce dernier utilise les Promises.
    Je découvre donc les mots-clés await et async, et j'ai écrit ce code (log() étant un wrapper de console.log()) :

    Code js : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    function registerGuild(guild) {
        let Promise1 = guild.members.fetch(userId);
        let Promise2 = guild.roles.fetch();
     
        log(1);
        let promiseExecution = async () => {
            log(3);
            let promise = await Promise.all([Promise1, Promise2]);
            log(4);
            return promise;
        }
        log(2);
        promiseExecution()
            .then(data => {/**/})
            .catch(console.error);
        log(5);
    }

    Je m'attends à voir 1 2 3 4 5, mais je vois 1 2 3 5. Et effectivement c'est comme si la fonction s'arrête subitement à la ligne 8. Pourtant le log(5) est bien executé.

    Je dois rater quelque chose mais je comprends pas.

  2. #2
    Expert confirmé
    Avatar de Doksuri
    Profil pro
    Développeur Web
    Inscrit en
    Juin 2006
    Messages
    2 465
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 465
    Points : 4 651
    Points
    4 651
    Par défaut
    le mot-clef "await" pourrait se traduire en francais par "attend"
    donc ta ligne 8 "attend" que Promise1 et Promise2 se resolvent pour continuer.

    il se peut que Promise1 ou Promise2 ne reponde pas... et c'est pour ca que tu ne vois pas ton log 4

  3. #3
    Membre émérite
    Avatar de Daïmanu
    Homme Profil pro
    Développeur touche à tout
    Inscrit en
    Janvier 2011
    Messages
    705
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur touche à tout

    Informations forums :
    Inscription : Janvier 2011
    Messages : 705
    Points : 2 475
    Points
    2 475
    Par défaut
    Citation Envoyé par Doksuri Voir le message
    le mot-clef "await" pourrait se traduire en francais par "attend"
    C'est bien ça qui me contrarie, je pensais que le mot-clé await faisait que la fonction promiseExection() attende que les deux Promise soient résolues, mais ça n'est pas le cas. Et je n'ai pas de message d'erreur.

    Cela dit le fait qu'une des Promise ne s'effectue pas correctement est une piste, je vais creuser par là.

  4. #4
    Expert éminent sénior
    Avatar de mathieu
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    10 305
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 10 305
    Points : 15 633
    Points
    15 633
    Par défaut
    Citation Envoyé par Daïmanu Voir le message
    je pensais que le mot-clé await faisait que la fonction promiseExection() attende que les deux Promise soient résolues
    oui c'est bien ce qu'il se passe, c'est pour ça que le "4" s'affiche plus tard.
    par contre, la fonction "registerGuild" démarre seulement la promesse "promiseExection" et n'attend pas la réponse, c'est pour ça que le "5" s'affiche à la suite.

    l'utilisation de async et await est juste une autre façon d'utiliser une promesse et "then", regardez cet exemple là :
    https://www.developpez.net/forums/d2.../#post11899853

  5. #5
    Membre émérite
    Avatar de Daïmanu
    Homme Profil pro
    Développeur touche à tout
    Inscrit en
    Janvier 2011
    Messages
    705
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur touche à tout

    Informations forums :
    Inscription : Janvier 2011
    Messages : 705
    Points : 2 475
    Points
    2 475
    Par défaut
    Merci pour le lien, je sentais que j'utilisais mal le then(), ça me simplifie les choses.

    Le souci vient visiblement de la fonction appelante, qui était ordinaire (sans await). En rajoutant ce mot-clé, ça attend bien comme je le veux.

    En passant de :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    function registerGuild(guild) {
        let promise1 = guild.members.fetch();
        let promise2 = guild.roles.fetch();
     
        let promiseExecution = async () => {
            return await Promise.all([promise1, promise2]);
        }
     
        promiseExecution()
            .then(data => {/* */})
            .catch(console.error);
    }
     
    client.on('messageCreate', message => {
        registerGuild(message.guild);
    }
    À ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    async function registerGuild(guild) {
        let promise1 = guild.members.fetch();
        let promise2 = guild.roles.fetch();
     
        const response = await Promise.all([promise1, promise2]);
        const x = response[0];
        const y = response[1];
        /* */
    }
     
    client.on('messageCreate', async message => {
        await registerGuild(message.guild);
    }
    J'ai réussi à faire marcher comme je le voulais, maintenant ce n'est peut-être pas la meilleure manière de faire.
    Je vais explorer encore un peu, mais en l'état ça me va.

  6. #6
    Expert éminent sénior
    Avatar de mathieu
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    10 305
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 10 305
    Points : 15 633
    Points
    15 633
    Par défaut
    dans l'évènement "messageCreate", vous n'attendez pas de valeur en retour donc je pense que vous pouvez simplifier comme cela :
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    client.on('messageCreate', message => registerGuild(message.guild));

    je viens de voir le souci dans votre 1re version du code, quand vous faites return await Promise.all([promise1, promise2]); vous retournez le résultat des 2 promesses et non une nouvelle promesse. regardez dans votre 2e version du code, vous faites la même chose.

  7. #7
    Membre émérite
    Avatar de Daïmanu
    Homme Profil pro
    Développeur touche à tout
    Inscrit en
    Janvier 2011
    Messages
    705
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur touche à tout

    Informations forums :
    Inscription : Janvier 2011
    Messages : 705
    Points : 2 475
    Points
    2 475
    Par défaut
    Citation Envoyé par mathieu Voir le message
    dans l'évènement "messageCreate", vous n'attendez pas de valeur en retour donc je pense que vous pouvez simplifier comme cela :
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    client.on('messageCreate', message => registerGuild(message.guild));
    Je ne l'ai pas précisé, mais il y a d'autres instructions dans cette fonction.

    Citation Envoyé par mathieu Voir le message
    je viens de voir le souci dans votre 1re version du code, quand vous faites return await Promise.all([promise1, promise2]); vous retournez le résultat des 2 promesses et non une nouvelle promesse. regardez dans votre 2e version du code, vous faites la même chose.
    Comment je fais alors pour attendre que les deux promesses soient terminées, pour passer à un mode synchrone ?

  8. #8
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    17 058
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 17 058
    Points : 44 588
    Points
    44 588
    Par défaut
    Bonjour,
    Comment je fais alors pour attendre que les deux promesses soient terminées, pour passer à un mode synchrone ?
    tu attends que les promesses soient terminées

    Plus sérieusement prenons un petit exemple.

    Commençons par la déclaration des promises :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const promise1 = new Promise((resolve, reject) => {
      resolve("first");
    });
    const promise2 = new Promise((resolve, reject) => {
      setTimeout(()=> resolve("second"), 1000);   // avec retard
    });
    const promise3 = new Promise((resolve, reject) => {
      resolve("third");
    });
    const promise4 = "etc ...";
    Nota : une promesse est crée avec un retard pour montrer qu'au final les retours seront bien dans l'ordre d'appel.

    Rappel : si une des promesses échoue la promesse Promise.all échoue.

    Créons une fonction d'appel pour résoudre celles-ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    function getResultat() {
      Promise.all([promise1, promise2, promise3, promise4])
        .then((response) => {
          // ici toutes les données sont disponibles dans l'ordre d'appel
          console.log("In promise :", response);
        });
    }
    ... les données sont traitées directement dans le then().

    On peut également traiter les réponses directement dans le then() en passant par une fonction de rappel, callback.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    function getResultat(callback) {
      Promise.all([promise1, promise2, promise3, promise4])
        .then((response) => {
          // ici toutes les données sont disponibles dans l'ordre d'appel
          callback && callback(response);
        });
    }
    ... cela permet souvent d'avoir un code plus lisible.

    Avec une fonction callback, l'appel pourrait ressembler à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    console.log("(1) Avant");
    getResultat((data) => {
      console.log("getResultat :", data);
      // ou tout autre fonction
    });
    console.log("(2) Après");
    Le résultat obtenu sera :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    > "(1) Avant"
    > "(2) Après"
    > "getResultat :" Array ["first", "second", "third", "etc ..."]


    Maintenant on pourrait envisager de traiter les données en retour de promesse, dans ce cas c'est une promesse qui est retournée, il nous faut donc utiliser le résultat dans le then().

    Créons une fonction d'appel pour résoudre celles-ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    function getResultat() {
      return Promise.all([promise1, promise2, promise3, promise4]);
    }
    Le traitement se fera dans le then() de la fonction getResultat(), qui est une promesse.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    console.log("(1) Avant");
    getResultat()             // appel de la fonction
      .then((data) => {       // traitement dans le then
        // ici toutes les données sont disponibles dans l'ordre d'appel
        console.log("Out promise :", data);
      })
    console.log("(2) Après");
    Le résultat sera le même que précédemment :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    > "(1) Avant"
    > "(2) Après"
    > "Out promise :" Array ["first", "second", "third", "etc ..."]

    Une autre façon de voir les choses avec le couple async/await serait cette forme par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    async function getResultat() {
      const response = await Promise.all([promise1, promise2, promise3, promise4]);
       // ici toutes les données sont disponibles dans l'ordre d'appel
      console.log("await :", response);
    }
     
    // appel à la fonction
    console.log("(1) Avant");
    getResultat();
    console.log("(2) Après");
    et toujours le même ordre dans la console :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    > "(1) Avant"
    > "(2) Après"
    > "await :" Array ["first", "second", "third", "etc ..."]
    Tu vois que tu as l’embarras du choix quant à la façon d'implémenter ton code

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Utiliser async/await sur une Promise (winsc)
    Par Tillt dans le forum NodeJS
    Réponses: 6
    Dernier message: 23/04/2021, 14h03
  2. Await / async & promise
    Par MaMz13 dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 17/07/2020, 11h28
  3. Promise, await/async ou callback
    Par lionelll dans le forum Général JavaScript
    Réponses: 9
    Dernier message: 05/11/2019, 14h04
  4. NodeJS : Promises & async/await
    Par Firlfire dans le forum NodeJS
    Réponses: 0
    Dernier message: 24/06/2019, 18h01
  5. [WSAD5] probleme incompréhensible
    Par capitaine_banane dans le forum Eclipse Java
    Réponses: 5
    Dernier message: 07/04/2004, 11h56

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo