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

NodeJS Discussion :

asynchrone synchrone attente fin de boucle


Sujet :

NodeJS

  1. #1
    Membre du Club
    asynchrone synchrone attente fin de boucle
    Bonjour à tous,
    je m'arrache le peu de cheveux qu'il me reste...
    je veux faire un truc tout bête, qui serrais fini en synchrone depuis longtemps mais en asynchrone j'ai du rater un truc.

    J'ai fait un exemple simple mais qui reflète déjà bien mon problème.

    j'ai une boucle avec un appel externe et à la fin de cette boucle je veux renvoyer le tableau.
    Comme vous pouvez le voir sur ce code tout est renvoyé avant que la boucle finisse

    Help
    j'ai surement du rater un gros truc mais ça alourdi considérablement bien le code le asynchrone, dommage qu'on ne puisse pas activer ou desactiver cette fonctionnalité...

    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
    const Request = require("request");
    const pers = ["pascal", "laurent", "marion", "melanie"]
    const pwd = "https://www.passwordrandom.com/query?command=guid&format=json&count=1"
    const tab = { "name": "", "pass": "" }
    var tokenTab = []
     
    function newpass(pe) {
        return new Promise(function (resolve, reject) {
            Request(pwd, function (error, response, body) {
                if (error) {
                    reject(error)
                }
                var pw = JSON.parse(body).char[0]
                resolve(pw)
            })
        })
    }
     
    async function start() {
        console.log("start")
        await step1();
        console.log(tokenTab)
        console.log("end")
     
    }
     
    function step1() {
     
        pers.forEach(el => {
            //console.log(el)
            newpass(el).then(z => {
                //console.log(z)
                var tt = tab
                tt.name = el
                tt.pass = z
                tokenTab.push(tt)
                console.log(tt)
            })
        })
     
    }
     
    start()
    -> SGBR=SQL SERVER 2014 <-

  2. #2
    Modérateur

    Bonjour,
    regarde du côté de l'utilisation de await qui met l’interpréteur « en pause ».

  3. #3
    Membre du Club
    j'ai déjà essayé mais j'y arrive pas ?
    je passe a coté d'un truc...


    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    const Request = require("request");
    const pers = ["pascal", "laurent", "marion", "melanie"]
    const pwd = "https://www.passwordrandom.com/query?command=guid&format=json&count=1"
    const tab = { "name": "", "pass": "" }
    var tokenTab = []
     
     
    function newpass(pe) {
        return new Promise(function (resolve, reject) {
            Request(pwd, function (error, response, body) {
                if (error) {
                    reject(error)
                }
                var pw = JSON.parse(body).char[0]
                resolve(pw)
            })
        })
    }
     
    async function start() {
        console.log("start")
        var tt = await step1();
        console.log("end")
    }
     
    function step1() {
        pers.forEach(async (el) => {
            //console.log(el)
            var ret = await newpass(el)
            console.log(ret)
        })
        console.log("fin de boucle")
    }
     
    start()
    -> SGBR=SQL SERVER 2014 <-

  4. #4
    Expert éminent
    L’idée du await rend le code plus simple à comprendre… En théorie. Le problème c’est la méthode .forEach qui ne «&#8239;comprend&#8239;» pas quand on lui passe une fonction async. Tu y arriverais avec une boucle for classique, à condition qu’elle soit elle-même dans une fonction async.

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    async function step1() {
     
        for (const el of pers) {
            //console.log(el)
            const z = await newpass(el)
            //console.log(z)
            var tt = tab
            tt.name = el
            tt.pass = z
            tokenTab.push(tt)
            console.log(tt)
        }
     
    }


    Mais il y a un inconvénient à cette façon de faire&#8239;: on perd le parallélisme des requêtes, car elles sont faites les unes à la suite des autres.

    Une solution plus efficace consiste à&#8239;:
    1. lancer toutes les requêtes en même temps dans une boucle synchrone qui n’attend pas les résultats&#8239;;
    2. utiliser Promise.all() pour renvoyer le tableau quand toutes les requêtes sont terminées.


    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
    17
    18
    19
    20
    21
    22
    23
    function step1() {
     
        const promises = []
     
        pers.forEach(el => {
            //console.log(el)
            promises.push(
                newpass(el).then(z => {
                    //console.log(z)
                    var tt = tab
                    tt.name = el
                    tt.pass = z
                    //tokenTab.push(tt) // tokenTab n’est plus nécessaire
                    console.log(tt)
                })
            )
        })
     
        Promise.all(promises).then((tokens) => {
          console.log(tokens);
        });
     
    }
    Cette signature n'a pas pu être affichée car elle comporte des erreurs.

  5. #5
    Membre du Club
    Merci Watilin,
    j'aime mieux l'idée d'envoyer les requêtes en asynchrone et d'attendre la fin de toutes les promesses.

    du coup j'ai fait le script avec ton exemple ça donne ça ...
    mais le resutat est surprenant.
    le log semble ok, mais le log du tableau des promesses ne fait apparaitre que le meme ????

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    { name: 'laurent', pass: '3f43385-0cd5-4eac-b57b-17506096fc49' }
    { name: 'marion', pass: 'd9c3eae-9b2b-4fc4-b6dd-47a9b34c1999' }
    { name: 'melanie', pass: '6e14885-e3c3-44c1-9941-81ee7eba874c' }
    { name: 'pascal', pass: 'eca99a8-0670-44f5-b78e-ae24c7c38885' }
     
    Resultat du tableau Promise.all ???
     
    [ { name: 'pascal', pass: 'eca99a8-0670-44f5-b78e-ae24c7c38885' },
      { name: 'pascal', pass: 'eca99a8-0670-44f5-b78e-ae24c7c38885' },
      { name: 'pascal', pass: 'eca99a8-0670-44f5-b78e-ae24c7c38885' },
      { name: 'pascal', pass: 'eca99a8-0670-44f5-b78e-ae24c7c38885' } ]



    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    const pers = ["pascal", "laurent", "marion", "melanie"]
    const pwd = "https://www.uuidgenerator.net/api/version4"
    const tab = { "name": "", "pass": "" }
    var rest = require('rest')
     
    async function newpass(per) {
        var pw = await rest(pwd)
        var ret = JSON.parse(JSON.stringify(pw.entity)).substring(1, 36)
        return ret
    }
     
    function step1() {
        const promises = []
        pers.forEach(el => {
            promises.push(
                newpass(el).then(z => {
                    var tt = tab
                    tt.name = el
                    tt.pass = z
                    console.log(tt)
                    return tt
                })
            )
        })
     
        Promise.all(promises).then((tokens) => {
            console.log(tokens);
        });
    }
     
    step1();
    -> SGBR=SQL SERVER 2014 <-

  6. #6
    Modérateur

    tu utilises un « pointer » sur ton objet tab en écrivant tt = tab, donc à chaque tour tu modifies en fait tab.
    Remplace ta ligne :

  7. #7
    Membre du Club
    pouaaaaa je m'aperçois que j'ai des mauvais reflexe d'autres langages.
    milles mercis je vais pouvoir terminer ce morceau... grace à vous tous.

    Merci.
    -> SGBR=SQL SERVER 2014 <-