2013-02-17 90 views
4

流行的JavaScript模塊Q實現了延期/承諾/期貨概念。我認爲它主要與node.js一起使用,但它也支持瀏覽器。我在node.js中使用它。通過node.js + Q進行同步回調延遲/承諾模塊

要做到連續通話要鏈接使用then()一個承諾,在未來,但在一個循環中它可以如此有悖常理比我發現很難做到與此相同的僞代碼:

forever { 
    l = getline(); 

    if (l === undefined) { 
     break; 
    } else { 
     doStuff(l); 
    } 
} 

將q文檔包括這似乎很相似的例子:但在嘗試許多方法來這個例子適應我的問題,我有沒有成功可言

var funcs = [foo, bar, baz, qux]; 

var result = Q.resolve(initialVal); 
funcs.forEach(function (f) { 
    result = result.then(f); 
}); 
return result; 

與示例代碼不同,我不是遍歷數組,而是希望循環直到滿足結束條件。另外我總是調用相同的功能。我的函數不會將之前的結果作爲下一次調用的參數。每個調用都沒有參數,但返回值決定是否繼續循環。

這些看似微不足道的差異造成了某種不可逾越的心理障礙。現在我明白了爲什麼許多人無法理解承諾。

回答

6

關鍵要記住的是,如果您從then回調承諾,那麼它將取代現有的承諾。這個想法是,在循環體中執行任何你想要做的事情鏈的一次迭代之後,你要麼返回一個值來解決承諾,要麼返回一個新的承諾,它將再次執行循環體。

function iterateUntil(endValue){ 
    // This line would eventually resolve the promise with something matching 
    // the final ending condition. 
    return Q.resolve('some value') 
    .then(function(value){ 
     // If the promise was resolved with the loop end condition then you just 
     // return the value or something, which will resolve the promise. 
     if (value == endValue) return value; 

     // Otherwise you call 'iterateUntil' again which will replace the current 
     // promise with a new one that will do another iteration. 
     else return iterateUntil(endValue); 
    }); 
} 
+0

我確實嘗試過,並且無法獲得迭代版本以及迭代版本。我會試試這個,但是沒有炸掉堆棧的風險嗎?我的項目將處理數百萬行的文本文件。 – hippietrail 2013-02-17 07:02:13

+1

@hippietrail這個遞歸解決方案應該可以工作。這不會導致堆棧因爲堆棧爲異步操作而重新啓動,所以'then'回調是從下一個進程打點開始的全新堆棧的開始。 – loganfsmyth 2013-02-17 07:36:14

+0

這似乎是工作,但我無法找到一種方法來捕捉結束條件。我的意思是我希望一些代碼只有在這個循環完成後才能執行。事實上,我非常肯定,由於行'if(value == endValue)返回值,它甚至沒有結束;因爲如果我打印它,我的endValue永遠不會顯示。在各個地方添加errbacks也不會導致任何被調用。而最糟糕的部分是Q似乎壓制了任何堆棧跟蹤 - 當它失敗時,它總是失敗。 – hippietrail 2013-02-17 10:20:57

0

這不是特定於問:Synchronous for loop

+0

我也在使用這些類型的循環,但是一旦你得到了一些嵌套的循環,特別是循環的不同風格,你最終會得到一種新的不可讀的意大利麪代碼。我經常困惑自己,並決定在這種情況下手工編碼沒有某種更具可讀性的抽象是要走的路。對於小腳本中的單個非嵌套循環,儘管我同意你的看法。 – hippietrail 2013-03-03 23:27:55