2014-05-21 70 views
0

我剛剛進入node.js並承諾(Q),所以請親切。 我想鏈與他的執行母鏈嵌套承諾,我無法找到如何。無法弄清楚如何將嵌套承諾鏈接到Q

我做了一個玩具腳本來說明我的PB,你可以用Node.js的啓動它:

var Q = require("q"); 

function init() { 
    return {nbIn: 0, nbOut: 0, stop: false}; 
} 

function fn1(ctx) { 
    var deferred = Q.defer(); 

    console.log("fn1:" + JSON.stringify(ctx)); 
    setTimeout(function() { 
     console.log("fn1: resolve"); 
     deferred.resolve(ctx); 
    }, 1000) 

    return deferred.promise; 
} 

function sub1(ctx) { 
    var deferred = Q.defer(); 

    console.log("sub1:" + JSON.stringify(ctx)); 
    setTimeout(function() { 
     ++ctx.nbIn; 
     console.log("sub1: resolve"); 
     deferred.resolve(ctx); 
    }, 1000); 

    return deferred.promise; 
} 

function sub2(ctx) { 
    var deferred = Q.defer(); 

    console.log("sub2:" + JSON.stringify(ctx)); 
    setTimeout(function() { 
     ++ctx.nbOut; 
     if(ctx.nbOut === 3) { 
      console.log("sub2: resolve"); 
      ctx.stop = true; 
      deferred.resolve(ctx); 
     } 
     else { 
      console.log("sub2: promise"); 
      return sub1(ctx).then(sub2); 
     } 
    }, 1000); 

    return deferred.promise; 
} 

function fn2(ctx) { 
    console.log("fn2:" + JSON.stringify(ctx)); 
    return sub1(ctx).then(sub2); 
} 

function fn3(ctx) { 
    console.log("fn3:" + JSON.stringify(ctx)); 
} 

Q.fcall(init).then(fn1).then(fn2).then(fn3); 

它顯示:

fn1:{"nbIn":0,"nbOut":0,"stop":false} 
fn1: resolve 
fn2:{"nbIn":0,"nbOut":0,"stop":false} 
sub1:{"nbIn":0,"nbOut":0,"stop":false} 
sub1: resolve 
sub2:{"nbIn":1,"nbOut":0,"stop":false} 
sub2: promise 
sub1:{"nbIn":1,"nbOut":1,"stop":false} 
sub1: resolve 
sub2:{"nbIn":2,"nbOut":1,"stop":false} 
sub2: promise 
sub1:{"nbIn":2,"nbOut":2,"stop":false} 
sub1: resolve 
sub2:{"nbIn":3,"nbOut":2,"stop":false} 
sub2: resolve 

我想鏈中的最後一行sub2fn3

任何幫助表示感謝,謝謝。

回答

0
setTimeout(function() { 
    … 
    return sub1(ctx).then(sub2); 
}, …) 

在這裏,我們從一個異步回調平原試圖return。你不能這樣做,結果將會丟失,因爲setTimeout不關心它。您可以從.then()回撥。在你的情況下,它應該是這樣的:

function sub2(ctx) { 
    var deferred = Q.defer(); 

    console.log("sub2:" + JSON.stringify(ctx)); 
    setTimeout(function() { 
     deferred.resolve(ctx); 
    }, 1000); 

    return deferred.promise.then(function(ctx) { 
     ++ctx.nbOut; 
     if (ctx.nbOut === 3) { 
      console.log("sub2: resolve"); 
      ctx.stop = true; 
      return ctx; 
     } else { 
      console.log("sub2: promise"); 
      return sub1(ctx).then(sub2); 
     } 
    }); 
} 

你也可以看到你總是使用Q.defer連同setTimeout現在。你應該爲那個返回承諾的幫助函數,並且use deferreds as seldom as possible

+0

好吧,我明白了。 'setTimeout'只是用來模擬真正的異步函數,比如'db.connect' /'query' /'insert'。 –

+0

那麼,這個觀點也適用於他們:將它們儘可能緊地包裹在助手函數(或者[以編程方式創建這些函數](http://stackoverflow.com/q/22519784/1048572))中,該函數只吐出承諾並做沒有處理。用這些承諾做所有的數據處理和流程邏輯。 – Bergi