2016-12-10 5 views
0

Ich habe users Liste in database:Promises Recursively

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

Hier ist meine findUsers Funktion: (Diese Funktion wie die Suche aus der Datenbank sieht Aber ich schreibe nur die einfache Funktion mit hartCodeDaten.)

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

ich möchte, dass alle Benutzer erhalten, die von userId beginnen:

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; 
}; 

Diese Funktion gibt das richtige Ergebnis zurück.

[ 
    { 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: [] } 
] 

Aber das ist nicht mein erwartet. Ich möchte Daten aus der Datenbank (Mungo)

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; 
    }); 
}; 

holen und diese Funktion fehlt Benutzer 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] ] } 
] 

Ich konnte nicht herausfinden, was bin ich falsch. Könnten Sie mir bitte helfen, es zu überprüfen?

Lassen users Daten überprüfen:

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: [] 
     }, 
    ] 
    }, 
]; 

Antwort

3

Sie müssen die folgenden Änderungen vorzunehmen:

  1. In Ihrem usrLst.forEach() Schleife reichern die Liste der Versprechen, die Sie bekommen und Promise.all() dann verwenden, so wissen Sie, wenn Sie sind alle fertig. Im Augenblick behalten Sie nicht die Übersicht, wann Ihre Anrufe bei walkUsers() überhaupt ausgeführt werden. Je nach Zeitpunkt können Sie also einige Ergebnisse verlieren oder verpassen.
  2. Dann müssen Sie dieses Master-Versprechen von Ihrem Handler zurückgeben, so dass es an die übergeordnete findUsers() Versprechen, die walkUsers() zurückgegeben wird verkettet ist.

, die wie folgt aussehen könnte:

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; 
     }); 
    }); 
}; 

Denken Sie daran, dass jedes Mal, wenn Sie einen asynchronen Vorgang innerhalb eines .then() Handler haben, sollte ein Versprechen fast immer von der .then() Handler zurückgegeben werden, so dass interne async Die Operation wird an die übergeordnete Operation angekettet, und dem Aufrufer wird nicht mitgeteilt, dass alles erledigt ist, bis alle verschachtelten asynchronen Operationen abgeschlossen sind. Wenn dies nicht der Fall ist, wird diese interne asynchrone Operation zu einer verwaisten asynchronen Operation, die zu ihrer eigenen Zeit abläuft und nichts darüber wartet oder mit ihr koordiniert und ob der Aufrufer sein Ergebnis sieht, ist eine Frage des Timings und des Codes funktioniert (was ein unsicheres Ergebnis ergibt).

+0

Vielen Dank. :) – Luc