2016-03-19 9 views
0

Ich habe ein JavaScript-Versprechen, wo ich den Wert zur Kartenfunktion, die leichter zu sehen, als das Problem mit zweiten Versprechen zu erklären, zurückgeben möchte. Ich weiß, dass ich keinen Wert innerhalb des Versprechens zurückgeben kann, aber ich frage, ob es eine bessere Lösung dafür gibt. DankWie gebe ich das Ergebnis von Versprechen zu Karte Funktion zurück

Mein Code:

const _     = require('lodash') 
    Boom    = require('boom'), 
    When    = require('when'), 
    User    = require('../../models/user'); 

var users; 
/** 
* Contact core functionality 
*/ 
users = { 


    /** 
    * Find user by id 
    * 
    * @param  {id} user id 
    * @returns  {Promise(User)} User 
    */ 
    findById: (id) => { 
     if (_.isEmpty(id)) { 
      return When.reject(Boom.badRequest('User id missing.')) 
     } 
     return User.get(id).run().then((user) => { 
      if (user) { 
       return When.resolve(user) 
      } 
      return When.reject(Boom.notFound('No user registered with provided id.')) 
     }).error((error) => { 
      return When.reject(error) 
     }); 
    }, 

    /** 
    * Returns all contacts of user from database 
    * @returns  [{Promise(Contact)}] contacts 
    */ 
    findContacts: (userId) => { 
     if (_.isEmpty(userId)) { 
      return When.reject(Boom.badRequest('User id missing.')) 
     } 
     return User.get(userId).run().then((user) => { 
      if (user) { 
       if(_.isObject(user.contacts)){ 
        user.contacts = _.map(user.contacts, (contact) => { 
         this.findById.then((user) => { 
          contact.user = user 
         }) 
         return contact 
        }) 
        return When.resolve(user.contacts) 
       } 
       return When.reject(Boom.notFound('No contacts registered with provided user.')); 
      } 
     }).error((error) => { 
      return When.reject(error) 
     }) 
    }, 
} 

Und das Problem hier:

   user.contacts = _map(user.contacts, (contact) => { 
        this.findById.then((user) => { 
         contact.user = user 
        }) 
        return contact 
       }) 
+0

Verwenden 'Promise.all' auf eine Reihe von Versprechungen. – Bergi

+0

@Bergi könnten Sie mir ein Beispiel mit meinem Code geben. Vielen Dank –

+0

Verwenden Sie keine lodash Karte. Verwenden Sie die Karte von wann. 'when.map (Array, yourFunction) .then (resultsArray => {/ * tada * /}' – Wainage

Antwort

0

Da Sie die Wenn Versprechen Bibliothek verwenden, sollten Sie eine eigene Iteratoren, wie map und reduce verwenden, um Verarbeite deine Arrays.

Eine Sache, die hier unglaublich wichtig ist, ist, dass in Wenn map läuft "opportunistisch" (läuft alles auf einmal parallel), während reduce läuft in Serie ohne Überschneidungen. Mit anderen Worten, wenn Sie ein Array mit 1000 Benutzern haben, sendet map (wahrscheinlich) 1000 Anfragen gleichzeitig an Ihre Datenbank, während reduce nicht beendet wird, bevor die Datenbankanforderungen nacheinander ausgeführt wurden.

So könnte Ihr Code wie folgt aussehen:

// This mutates user.contacts, so you don't need to worry about the 
// 'initial value' in your reducer function 
When.reduce(user.contacts, (carry, contact) => { 
    return this.findById.then((user) => { 
     contact.user = user 
    }) 
}); 

Wenn Sie eine Tonne Benutzer tun müssen, verarbeiten, könnte es mehr Sinn, chunk machen Sie Ihre Daten in einer Reihe von kleineren, vernünftig bemessenen Arrays; Sie würden reduce die Chunks und map die Benutzer in jedem Stück. Dies würde bedeuten, dass das Array viel schneller verarbeitet werden könnte, als wenn es seriell erfolgt, ohne dass die Gefahr besteht, dass Ihre Datenbank beschädigt wird.

bearbeiten

// This mutates user.contacts, so you don't need to worry about the 
// 'initial value' in your reducer function 
// It also returns the array of users as `allContacts` 
var allContacts = When.reduce(user.contacts, (carry, contact) => { 
    return this.findById.then((user) => { 
     contact.user = user 
     carry.push(user); 
     return carry; 
    }) 
}, []); 
+0

Ich erhalte diesen Fehler this.findById ist keine Funktion I Sache, weil findById es ein Versprechen ist –

+0

Wenn Sie eine Pfeilfunktion verwenden, sollte 'This sein was es außerhalb des Versprechens war (oder vielmehr außerhalb der Pfeilfunktion selbst) was "das" ist und von dort ausgehen. Wenn Sie eine schnelle Auflösung wünschen, verwenden Sie eine Closure-Variable ('let scope = this;' ... 'scope.findById().') – Andrew

+0

großartig jetzt funktioniert es aber Versprechen zurück undifed –