[英]How To Synchronise Promise Objects?
我有承諾需要同步的對象。 例如,第二個承諾在第一個承諾完成之前不應該起作用。 如果第一個拒絕,則必須再次執行。
我已經實現了一些例子。這個很好用。 調用getVal,等待2000ms,返回,i ++,再次調用getVal .....
getVal() {
return new Promise(function(resolve, reject) {
setTimeout(function(){ resolve(19) }, 2000);
});
}
async promiseController(){
for(var i =0;i<5;i++)
{
var _val = await this.getVal()
console.log(_val+'prom');
}
}
但我需要控制一組promise對象。 我想要做的是我有一個數據,我把它分成5塊。 在處理完第一部分(例如:發送到服務器)后,我想要處理第二部分,否則我必須再次處理第一部分。
這是我制作的原型實現
getVal() {
return new Promise(function(resolve, reject) {
setTimeout(function(){ resolve(19) }, 2000);
});
}
async promiseController(){
var proms=[]
for(var i =0;i<5;i++)
{
proms.push(this.getVal())
}
for(var i =0;i<5;i++)
{
var _val = await proms[i]
console.log(_val+'prom');
}
}
此代碼中的Promises對象按順序工作。 我如何修復下面的代碼,以便它作為第一個例子同步工作。
async promiseController(){
for(const value of array) {
console.log((await this.getVal(value))+'prom');
}
}
無需過度復雜化。 只需在循環中調用await
,它就會等待你想要的東西。
正如另一個答案所說的那樣 - 承諾代表一種價值,而不是一種操作。 對於操作,使用常規功能。
如果你想忽略失敗,你可以在.catch(() => {})
。 如果要重試直到失敗 - 您可以重構重試函數並使用它:
const retry = fn => (...args) => fn(...args).catch(retry(fn));
如果您的目標是在第一個承諾解決之前不“執行后續承諾”,那么您需要記住,承諾代表已經在飛行中的異步活動。 一旦承諾存在,就為時已晚。
在第一個promise完成之前,您需要不要調用后續的promise工廠方法。 您的第一個示例通過在上一個promise完成之前不調用getVal()
完成此操作。
所以你最終得到的結果如下:
delay(time) {
return new Promise(resolve => setTimeout(resolve, time));
}
async promiseController() {
const factories = [];
for (let i = 0; i < 5; ++i) {
factories.push(() => this.getVal());
}
for (const f of factories) {
// keep running this factory until it succeeds
let success = false;
while (!success) {
try {
const promise = f();
const result = await f;
success = true;
console.log(`result = ${result}`);
}
catch (err) {
console.log("promise failed. retrying");
await delay(100);
}
}
}
}
你可以使用遞歸,命名函數, .then()
var arr = [Promise.resolve("a") , Promise.resolve("b") , Promise.resolve("c")]; var i = 0; var res = []; function foo() { // conditional resolved or rejected promise var n = String(new Date().getTime()).slice(-1); // if `n` < 5 reject `n` , else resolve `n` var curr = n < 5; return curr ? arr[i] : Promise.reject(["rejected", n]) } var p = (function repeat() { var promise = foo(); return promise .then(function(data) { console.log(data); res.push(data); ++i; if (i < arr.length) return repeat() // return `res` array when all promises complete else return res }) .catch(function(err) { console.log(err); if (err[0] === "rejected") return repeat() }) }()); p.then(function(complete) { console.log("complete:", complete) });
好吧 我相信為了正確的函數編程目的,應避免使用async
和await
thingy。 我相信承諾非常充足。 然而,如果您想繼續使用C ++進行編碼,那么async
和await
適合您。
我有承諾需要同步的對象。 例如,第二個承諾在第一個承諾完成之前不應該起作用。 如果第一個拒絕,則必須再次執行。
讓我簡單介紹下面的代碼。 我們有async()
函數,它接受數據和回調(錯誤優先類型)。 至於演示目的,它將嘗試在2000ms內使用數據調用回調,但是在1000ms處有超時。 所以50-50它將調用帶有數據或錯誤的回調。
所以我們實際上需要它給我們一個承諾,所以我在promisify()
的幫助下promisify()
它,它需要async()
函數並返回asyncPro()
函數。 這實際上與async()
相同,但返回一個promise。 所以我們期望在then
階段使用我們的回調。
然后是tryNTimes(data,asyncFun,n = 5)
函數,它接受數據,一個promisified異步函數和一個整數,指定在拒絕它之前嘗試的次數。 它的默認嘗試次數為5,但您可以通過傳遞第三個參數將其設置為任何值。
至於最后一部分,我們有了flowControl()
,它在Array.prototype.reduce()
的幫助下完美地鏈接了我們的promise。
所以現在我們將所有的承諾一個接一個地鏈接起來,在嘗試5次之前沒有一個會失敗。
function promisify(fun){ return (data) => new Promise((resolve,reject) => fun(data, (err,res) => err ? reject(err) : resolve(res))); } function async(data, callback){ var dur = Math.floor(Math.random()*2000); setTimeout(_ => callback(false,data),dur); // may resolve before timeout setTimeout(_ => callback("error at " + data),1000); // timeout at 1 sec } function tryNTimes(data,asyncFun,n = 5){ return new Promise((resolve,reject) => { n === 0 && reject("try out fail at 5 tries: " + data); asyncFun(data).then(v => resolve("resolved at countdown " + n + ": " + v)) .catch(e => resolve(tryNTimes(data,asyncFun,--n))); }); } function flowControl(d,f,tc){ return d.reduce((prom,chunk) => prom.then(v => { console.log(v); return tryNTimes(chunk,f,tc); }),Promise.resolve("initial dummy promise")); } var data = ["chunk_1", "chunk_2", "chunk_3", "chunk_4", "chunk_5"], asyncPro = promisify(async); // now our async function returns a promise flowControl(data,asyncPro).then(v => console.log(v)) .catch(e => console.log(e));
如果您希望更頻繁地看到“5次嘗試”錯誤,請降低async()
函數中的超時值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.