2016-12-10 1 views
0

J'ai users liste database:promesses récursive

let users = []; // Please check the full list at the end of this post

Voici ma fonction findUsers: (Cette fonction ressemble à la recherche de la base de données Mais j'écris juste la simple fonction des données difficiles code.)

function findUsers(user) { 
    return new Promise(function (resolve) { 
    resolve(user.users); 
    }); 
} 

Je veux obtenir tous utilisateurs qui commencent par userId:

const walkUsers = (user, list) => { 
    let usrLst = user.users; 
    list = list || []; 
    usrLst.forEach((usr) => { 
    if (usr.users.length > 0) { 
     list = walkUsers(usr, list); 
    } 
    list.push(usr); 
    }); 
    return list; 
}; 

Cette fonction renvoie un résultat correct.

[ 
    { id: '009', name: 'User 9', users: [] }, 
    { id: '011', name: 'User 11', users: [] }, 
    { id: '010', name: 'User 10', users: [ [Object] ] }, 
    { id: '004', name: 'User 4', users: [ [Object], [Object] ] }, 
    { id: '003', name: 'User 3', users: [ [Object] ] }, 
    { id: '007', name: 'User 7', users: [] }, 
    { id: '002', name: 'User 2', users: [ [Object], [Object] ] }, 
    { id: '008', name: 'User 8', users: [] }, 
    { id: '005', name: 'User 5', users: [ [Object] ] }, 
    { id: '006', name: 'User 6', users: [] } 
] 

Mais ce n'est pas mon attendu. Je veux récupérer les données de base de données (Mongoose)

const walkUsers = (user, list) => { 
    return findUsers(user) 
    .then((usrLst) => { 
     list = list || []; 
     usrLst.forEach((usr) => { 
     if (usr.users.length > 0) { 
      walkUsers(usr, list).then((rtnLst) => { 
      console.log("rtnLst"); 
      console.log(rtnLst); 
      return rtnLst; 
      }); 
     } 
     list.push(usr); 
     }); 

     return list; 
    }); 
}; 

Et cette fonction est manquant utilisateur 009, 010, 011

[ 
    { id: '002', name: 'User 2', users: [ [Object], [Object] ] }, 
    { id: '005', name: 'User 5', users: [ [Object] ] }, 
    { id: '006', name: 'User 6', users: [] }, 
    { id: '003', name: 'User 3', users: [ [Object] ] }, 
    { id: '007', name: 'User 7', users: [] }, 
    { id: '008', name: 'User 8', users: [] }, 
    { id: '004', name: 'User 4', users: [ [Object], [Object] ] } 
] 

Je ne pouvais pas comprendre ce que je me trompe. Pourriez-vous s'il vous plaît m'aider à vérifier?

permettent de vérifier users données:

let users = [ 
    { 
    id: '001', 
    name: 'User 1', 
    users: [ 
     { 
     id: '002', 
     name: 'User 2', 
     users: [ 
      { 
      id: '003', 
      name: 'User 3', 
      users: [ 
       { 
       id: '004', 
       name: 'User 4', 
       users: [ 
        { 
        id: '009', 
        name: 'User 9', 
        users: [] 
        }, 
        { 
        id: '010', 
        name: 'User 10', 
        users: [ 
         { 
         id: '011', 
         name: 'User 11', 
         users: [] 
         }, 
        ] 
        }, 
       ] 
       } 
      ] 
      }, 
      { 
      id: '007', 
      name: 'User 7', 
      users: [] 
      } 
     ] 
     }, 
     { 
     id: '005', 
     name: 'User 5', 
     users: [ 
      { 
      id: '008', 
      name: 'User 8', 
      users: [] 
      } 
     ] 
     }, 
     { 
     id: '006', 
     name: 'User 6', 
     users: [] 
     }, 
    ] 
    }, 
]; 

Répondre

3

Vous devez apporter les modifications suivantes:

  1. Dans votre boucle usrLst.forEach(), accumulez la liste des promesses que vous obtenez et utilisez Promise.all() afin de savoir quand ils sont tous faits. En ce moment, vous ne gardez aucune trace de quand vos appels à walkUsers() sont faits du tout, donc en fonction du timing, vous pouvez perdre ou manquer des résultats.
  2. Ensuite, vous devez renvoyer cette promesse principale à partir de votre gestionnaire .then() afin qu'il soit chaîné à la promesse parent findUsers() qui renvoie walkUsers().

Cela pourrait ressembler à ceci:

const walkUsers = (user, list) => { 
    return findUsers(user) 
    .then((usrLst) => { 
     list = list || []; 
     var promises = []; 
     usrLst.forEach((usr) => { 
     if (usr.users.length > 0) { 
      promises.push(walkUsers(usr, list)); 
     } 
     list.push(usr); 
     }); 

     return Promise.all(promises).then(function() { 
      // make the list be the resolved value from this promise 
      return list; 
     }); 
    }); 
}; 

Gardez à l'esprit que chaque fois que vous avez une opération asynchrone dans un gestionnaire .then(), une promesse doit presque toujours être retournée par le gestionnaire .then() afin que async interne L'opération est chaînée à l'opération parente et l'appelant ne sera pas informé que les opérations sont terminées jusqu'à ce que toutes les opérations asynchrones imbriquées soient terminées. Sinon, cette opération asynchrone interne devient simplement une opération asynchrone orpheline qui fonctionne sur son propre temps et rien au-dessus ne l'attend ou ne coordonne avec elle et si l'appelant voit son résultat sera une question de chance de timing et comment votre code fonctionne (ce qui rend un résultat incertain).

+0

Merci beaucoup. :) – Luc