2015-04-16 142 views
3

下一篇文章我的鬥爭充分掌握的諾言......簡單的承諾隊列:q.all解決之前推遲承諾解決

我想創建一個簡單的承諾隊列(與節流查詢的長期目標在數據庫上),然後我可以使用Q.all()和Array.protoype.map()。

(這似乎涉及到this question,但我沒有看到有一個明確的決議。)

這裏是我的簡單的框架:

var Q = require('q'); 

var queue = []; 
var counter = 0; 
var throttle = 2; // i can do things at most two at a time 

var addToQueue = function(data) { 
    var deferred = Q.defer(); 
    queue.push({data: data, promise: deferred}); 
    processQueue(); 
    return(deferred.promise); 
} 

var processQueue = function() { 
    if(queue.length > 0 && counter < throttle) { 
     counter++; 
     var item = queue.shift(); 
     setTimeout(function() { // simulate long running async process 
      console.log("Processed data item:" + item.data); 
      item.promise.resolve(); 
      counter--; 
      if(queue.length > 0 && counter < throttle) { 
      processQueue(); // on to next item in queue 
      } 
     }, 1000); 
    } 
} 

data = [1,2,3,4,5]; 
Q.all(data.map(addToQueue)) 
    .then(console.log("Why did get here before promises all fulfilled?")) 
    .done(function() { 
     console.log("Now we are really done with all the promises."); 
    }); 

但是,正如前文所提到的「再「立即被調用,並且只有」完成「被推遲,直到解決所有的承諾。我注意到在api documentation中,唯一的例子確實使用.done()和not then()。所以也許這是預期的行爲?問題是,那麼我不能連鎖其他行動。在這種情況下,我需要創建另一個延期的承諾,解決它在Q.all的實現功能如下

data = [1,2,3,4,5]; 

var deferred = Q.defer(); 

deferred.promise 
    .then(function() { 
     console.log("All data processed and chained function called."); 
    }) // could chain additional actions here as needed. 

Q.all(data.map(addToQueue)) 
    .done(function() { 
     console.log("Now we are really done with all the promises."); 
     deferred.resolve(); 
    }); 

到,根據要求的作品,但額外的步驟,讓我覺得我必須失去了一些有關如何正確使用Q.all()。

Q.all()的使用是否有問題,或者上面的額外步驟實際上是正確的方式嗎?

編輯:

Tyrsius指出我的論點來。那麼是不是一個函數的引用,但緊接着的評價功能(執行console.log(...))。下面是我應該怎麼做的:

Q.all(data.map(addToQueue)) 
    .then(function() { console.log("Ahhh...deferred execution as expected.")}) 

回答

4

其實你的問題是標準的Javascript。

Q.all(data.map(addToQueue)) 
    .then(console.log("Why did get here before promises all fulfilled?")) 
    .done(function() { 
     console.log("Now we are really done with all the promises."); 
    }); 

仔細看第二行。 Console.log立即被註銷並作爲參數被髮送到.then。這與promise沒有任何關係,只是javascript如何解析函數調用。你需要這個

Q.all(data.map(addToQueue)) 
     .then(function() { console.log("Why did get here before promises all fulfilled?")}) 
     .done(function() { 
      console.log("Now we are really done with all the promises."); 
     }); 

編輯

如果這是你做了很多的東西,你可以做一個函數返回函數的作品你想

function log(data) { 
    return function() { console.log(data);} 
} 

Q.all(data.map(addToQueue)) 
     .then(log("Why did get here before promises all fulfilled?")) 
     .done(function() { 
      console.log("Now we are really done with all the promises."); 
     }); 
+0

AARGH方式。連續燃燒兩次,立即評估!謝謝你指出。 – Eric

+1

@Eric看到我的編輯速記,可以爲您節省一些麻煩 – Tyrsius

+0

您也可以編寫'.then(console.log.bind(console,'message'))''。 –