2017-03-01 3 views
0

Unten sehen Sie, wo ich ein Problem im kommentierten Code habe. Ich habe ein verschachteltes Versprechen, das ein Objekt in einer Sammlung erstellt und dann zurückgibt.Verschachtelte Versprechen können nicht zur nächsten Versprechenskette zurückgegeben werden

Aber ich denke, ich habe ein Problem mit Async. Die Funktion wird abgeschlossen, bevor das erstellte Objekt vom verschachtelten Versprechen zurückgegeben wird.

Ich fasse immer noch Versprechen Verkettung, und ich mache wahrscheinlich viel falsch hier. Vieles davon könnte aufgeklärt werden, wenn ich etwas davon reinigen/reduzieren könnte.

PostSchema.statics.createPost = function (o, user) { 
    var whiskey; 
    return Whiskey 
     .createWhiskey(o.whiskey.value) 
     .then(function (whiskeyData) { 
      whiskey = whiskeyData.whiskey; 
      o.post.whiskey = whiskeyData.whiskey._id; 

      if (whiskeyData.whiskey.distiller) { 
       o.post.distiller = whiskeyData.whiskey.distiller; 
      } 

      return o.distiller.new === true && !whiskey.distiller ? Distiller.newDistiller(o.distiller.value) : Promise.resolve() 
       .then(function (distiller) { 
        //this never invokes <---- it's called from the function below 
        console.log('never invokes', distiller). 
        if (distiller) { 
         whiskey.distiller = distiller._id; 
         //test this save 
         whiskey.save(); 
         o.post.distiller = distiller._id; 
        } 

        var post = o.post; 
        post.user = user._id; 
        return Post 
         .createAsync(post) 
         .then(function (data) { 
          return Post 
           .populate(data, { 
            path: 'user whiskey', 
            populate: { 
             path: 'distiller style', 
            } 
           }) 
         }) 

         .then(function (populatedData) { 
          return (user.shareFB ? social.checkFB(user, populatedData) : Promise.resolve()) 
           .then(function (FBres) { 
            return (user.shareTWT ? social.checkTWT(user, populatedData) : Promise.resolve()) 
             .then(function (TWTres) { 
              var socialData = [TWTres, FBres]; 
              return { 
               'post': populatedData, 
               'social': socialData 
              }; 
             }) 
           }) 
         }) 
       }) 
     }) 
     .catch(function (err) { 
      console.log('post create err : ', err); 
     }) 
}; 

das ist, wo der Brenner erzeugt und zurück versuchen:

DistillerSchema.statics.newDistiller = function (o) { 

    return Distiller 
     .findAsync({ 
      'name': o.name 
     }) 
     .then(function (distiller) { 
      if (distiller.length) { 
       return distiller[0]; 
      } 
      return Distiller 
      .createAsync(o) 
      .then(function (data) { 
       //console.log here indicates that is is created <-- created and returned here 
       console.log('distiller created ', data) 
       return data; 
      }) 
     }) 
     .catch(function(err) { 
      console.log('create distiller err ', err); 
     }) 
}; 
+1

Wenn Ihr Code 9 Ebenen tief verschachtelt, dann können Sie bereits feststellen, dass Sie nicht die richtigen Versprechen halten. Verschachteln Sie nicht. Kette. – trincot

+0

Promise.resolve() übergibt undefined an die nächste Funktion in der Kette. 'Funktion (whiskyData) { whiskey = whiskyData.whiskey;' wird brechen, wenn WhiskeyData nicht definiert ist, wird direkt zum Fang übersprungen – lonewarrior556

+0

Ja, ich sollte das Ternär entfernen. Whisky ist ein Pflichtfeld. – NoobSter

Antwort

1

Klingt wie eine Gruppierung Fehler. Statt

return o.distiller.new === true && !whiskey.distiller 
    ? Distiller.newDistiller(o.distiller.value) 
    : Promise.resolve().then(…) // callback only called when no new distiller 

wollen Sie

return (o.distiller.new && !whiskey.distiller 
    ? Distiller.newDistiller(o.distiller.value) 
    : Promise.resolve() 
).then(…) // callback always called 

Mindestens das ist, wie die anderen conditionals alle :-)

tat

Ich Greifen noch Versprechen Verkettungs

Nachdem Sie gelernt haben, dass Sie immer return von Ihren asynchronen Funktionen benötigen (was Sie gut gemacht haben), sollten Sie einen Blick auf how it is possible to flatten a chain (was für Ihren Code gilt, wenn alle Bedingungen nur lokale Ausdrücke sind, nicht vorzeitig zurück). Außerdem würde ich empfehlen, verkettete Methodenaufrufe nicht einzuziehen, da diese beim Verschachteln von then Rückrufen schnell außer Kontrolle geraten, aber das ist nur meine persönliche Vorliebe.

+0

Danke @Bergi. Ich kann nicht glauben, dass ich das verpasst habe. Schätzen Sie die Versprechen Mentorschaft! – NoobSter

Verwandte Themen