簡體   English   中英

在履行時將promise的數組轉換為值數組

[英]Transform array of promises into array of values when fulfilled

我正在使用一個函數來返回一個已解決的promise值。 優雅地失敗肯定是一個獎勵,但它是一個假設的前提條件,當函數被調用時,諾言已准備好被解決。

雖然我正在使用webdriver.js承諾實現 ,它允許類似於下面的隊列操作,但我不想在隊列/鏈等的語義上太丟失。僅僅因為這個原因,這里有一些偽代碼來覆蓋我的內容我想要實現:

var inputs = [...], outputs;
outputs = inputs.map(function(input){
  //queue some async tasks to be performed with input
  queue.enqueue(...);
  //I can't return the *output* value here yet, naturally, so instead
  return promise;
});

//now I'll add another task to the same queue
//this means that by the time this task is run
//the async tasks above would have been executed
//and the promises would be "resolvable"... right?
queue.enqueue(function(){
  console.log(outputs); //>an array of promises
  console.log(doSomeMagic(outputs)); //>resolved values as needed <<<
});

注意:afaik Q.all() 不會做我正在做的事情 - 它需要一組承諾並返回一個數組的承諾, 而不是它的已解析值 我很高興被證明是錯的。

獲得承諾的最終價值的唯一方法就是then 如果函數異步執行工作,它必須返回一個promise,在任何情況下都不能返回一個普通值。 要做到這一點,它必須阻止執行的線程,直到工作完成,這只能通過線程或光纖來實現,這會帶來死鎖和交錯危險的危險。

因此, Q.all 其實你需要的,除了跟進與方法then得到最終值。

Q.all(inputs.map(function (input) {
   return promiseForOutput; // however you go about this 
}))
.then(function (outputs) {
   // at this event, outputs is an array of output values
});

當然,還有辦法欺騙。 promise.inspect()將返回一個描述promise的狀態的對象,如{state: "fulfilled", value: value}如果它已經准備好,或{state: "rejected", error}如果失敗,或者{state: "pending"} ,如果尚未准備好。 如果,如你所說,保證Q.all返回的outputs承諾已經完成,你可以這樣做:

outputs = outputs.inspect().value

我不推薦這個。 知道承諾得到解決的最好方法是使用then

如果您還可以通過某些外部手段保證所有outputs都已准備就緒,您也可以將值推送到您的outputs數組中。

var endResult = Q.defer();

var outputs = [];
inputs.forEach(function (input) {
    outputPromise.then(function (output) {
        outputs.push(output);
        check();
    }, endResult.reject);
});
check();

function check() {
    if (outputs.length === inputs.length) {
        // manipulate outputs directly, they are ready
        endResult.resolve();
    }
}

return endResult.promise;

然而,最好的方法是使用Q.all(outputs).then來確保在所有輸出都准備好之后的事件。

由於您通常不知道承諾是否得到解決,因此您不能簡單地將它們轉換為普通值。 Q.all必須返回一個promise,因為它無法從異步上下文中提取values數組。 唯一一次你知道一個promise有一個值就在成功處理程序中,無論如何你都會得到這個值。 您不應該使用另一個事件系統來告訴您承諾何時結算 - 使用承諾本身。

所以不要使用queue.enqueue ,只需Q.all(outputs).then(function(values){ /* do something */ }) 但是,如果你_.pluck(_.invoke(outputs, "inspect"), "value")這個問題,你可能會看看Promise inspect調試方法_.pluck(_.invoke(outputs, "inspect"), "value") 但請注意,然后可能更容易不將值存儲在promises中。

對於其他任何根據問題標題尋找答案的人,以下與ES 2017+一起使用以獲取一系列承諾並返回一組值:

var arrayOfValues = await Promise.all(arrayOfPromises)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM