2017-03-25 3 views
0

Ich versuche, einige dynamische Abfragen sequentiell zu tun, aber aus irgendeinem Grund, erfüllt der nächste Code dieses gewünschte Verhalten nicht.mongoose sequentielle Versprechen

var createEvent = function (user, notification) { 
    var action, query; 

    query = { agent: notification.agent, story: notification.story, type: notification.type }; 
    action = { agent: notification.agent, story: notification.story, type: notification.type, ts: notification.ts }; 

    return mongoose.model('Event').findOne(query).exec() 
    .then(function (response) { 
     if (response === null) { 
     return mongoose.model('Event').create(action) 
      .then(function (response) { 
      return mongoose.model('User').findByIdAndUpdate(user, { $push: { notifications: { _id: response._id }}}); 
      }); 
     } 
     return mongoose.model('User').findByIdAndUpdate(user, { $push: { notifications: { _id: notification._id }}}).exec(); 
    }); 

    setTimeout(resolve, 3000); 
}; 

var moveNotifications = function (users) { 
    var promises = []; 

    users.map(function (user) { 
    if (user.notifications.length > 0) { 
     user.notifications.map(function (notification) { 
     promises.push(createEvent(user._id, notification)); 
     }); 
    } 
    }); 

    Promise.each(promises, function (queue_item) { 
    return queue_item(); 
    }); 
}; 

Könnte mir jemand helfen?

+0

paar Dinge ... 'setTimeout (resolve, 3000);' wird nie ausgeführt, weil es nach einem 'return' ist - aber das ist genauso gut,' resolve' ist sowieso nicht definiert. Zweitens rufen Sie 'createEvent' in einem .map-Callback auf - also sind alle diese' findOne' Aufrufe "im Flug" vor dem ersten .Dann kann –

Antwort

1

Wie Sie createEvent innerhalb der verschachtelten Array#map Schleifen anrufen, Sie beginnen sofort alle Abfragen - was Sie tun möchten, ist erhalten nur eine Reihe von id und notification zu später createEvent passieren in Promsise.each

Hinweis Nicht sicher, warum Sie Array#map verwenden, wie Sie noch nie etwas von der Karte Rückruf zurückkehren - Sie tun im Grunde Array#forEach

var moveNotifications = function(users) { 
    var items = []; 
    users.forEach(function(user) { 
     if (user.notifications.length > 0) { 
      user.notifications.forEach(function(notification) { 
       items.push({id: user._id, notification: notification}); 
      }); 
     } 
    }); 
    return Promise.each(events, function(item) { 
     return createEvent(item._id, item.notification); 
    }); 
} 

Alternativ Array#concat mit

  • Pfeil: ein 2-Level-Array zu glätten, die richtig unter Verwendung von (verschachtelte) Array#map zurückgegeben wird, können Sie die oben leicht gemacht noch prägnanter die folgende ES2015-Syntax mit dem gleichen Ergebnis

    var moveNotifications = function(users) { 
        return Promise.each([].concat.apply([], users.map(function(user) { 
         return user.notifications.map(function(notification) { 
          return {id: user._id, notification: notification}; 
         }); 
        })), function(item) { 
         return createEvent(item._id, item.notification); 
        }); 
    } 
    

    erreichen => Funktionen

  • Verbreitung Betreiber ...
  • Stenografie Objekteigenschaftsnamen {a, b, c}
  • Context Parameter Passende ({a, b, c}) =>

var moveNotifications = users => 
    Promise.each([].concat(...users.map(user => 
     user.notifications.map(notification => ({id: user._id, notification})) 
    )), ({id, notification}) => createEvent(id, notification) 
); 

Die extreme ES2016 einzeiler Version - 10

  • Destrukturierung Zuordnung: p

    var moveNotifications = users => Promise.each([].concat(...users.map(user => user.notifications.map(notification => ({id: user._id, notification})))), ({id, notification}) => createEvent(id, notification)); 
    
  • +0

    genannt werden. Ich verstand das Konzept der Erstellung iterativer Versprechen nicht! Also danke für diese Antwort finde ich es noch deutlicher! Vielen Dank! – DevStarlight

    Verwandte Themen