[英]Break a Promise chain inside for-loop
我正在研究一個受此答案啟發的承諾鏈: https : //stackoverflow.com/a/44955506/7485805
我想打破此for循環,以正確處理鏈的拒絕。 我只是想知道我不能在鏈的.catch
方法中使用break
。
這是我的代碼,如果有幫助的話:
function pro (arr) {
let chain = Promise.resolve();
const self = {req: {}, res: {}};
const length = arr.length;
return new Promise((resolve, reject) => {
for(let i=0; i<length; i++){
chain = chain
.then(() => arr[i].call(self) )
.then(() => {
if(i === (length - 1) )
resolve();
})
.catch(e => {
reject(e);
})
}
})
.then(() => {
return self
})
.catch(e => {
throw new Error (e);
})
}
const x = function () {
const self = this;
return new Promise(resolve => {
self.req = {key: "value"}
resolve();
})
}
const y = function () {
const self = this;
return new Promise((resolve, reject) => {
console.log(self);
reject();
})
}
const z = function () {
const self = this;
return new Promise((resolve, reject) => {
console.log('failed');
})
}
pro([x, y, z])
.then((self) => {
console.log('final',self);
})
.catch(e => {
console.log('error', e);
})
x, y, z
在功能串連在一起三種功能pro
雖然, x
成功解析, y
執行,但被拒絕。
我想停止執行z
因為繼續執行毫無意義,並可能在實際代碼中產生錯誤。
另外,如果有人可以向我推薦這段代碼的更好版本:
.then(() => {
if(i === (length - 1) )
resolve();
})
注意:我無法使用await
因為此代碼將在服務器端執行,並且使用await
可能會阻止其他傳入請求。
使用async/await
語法要容易得多:
async function pro(arr) {
const self = {req: {}, res: {}};
for(const f of arr) await f.call(self);
return self;
}
async function pro(arr) { const self = {req: {}, res: {}}; for(const f of arr) await f.call(self); return self; } const x = function () { const self = this; return new Promise(resolve => { self.req = {key: "value"} resolve(); }) } const y = function () { const self = this; return new Promise((resolve, reject) => { console.log(self); reject("y failed"); }) } const z = function () { const self = this; return new Promise((resolve, reject) => { console.log('failed'); }) } pro([x, y, z]).then((self) => { console.log('final',self); }) .catch(e => { console.log('error', e); });
一些事情:當您在for循環中構造您的Promise鏈時,就是這樣:鏈被構造。 .then
執行最早在下一個事件循環中發生。 我將嘗試說明:
var promiseChain = functionReturningPromise();
for(var i=0;i<3;i++){
promiseChain = promiseChain.then(x=> {
return anotherPromiseFunction(x);
});
}
根據ReturningPromise實際執行的functionReturningPromise
,此時可能已經發生了某些事情……或可能沒有。 例如,我們可能已經開始了fetch
,或者開始了WebWorker.
但是,如果在第一個Promise中嵌套了setTimeout
,那么我們所做的就是將setTimeout
回調放入隊列中,以進行事件循環的下一個周期。 但是保證100%,沒有.then
函數尚未運行。 稍后,在下一個事件循環中。
因此,下一個事件循環到來,並且承諾已經解決。 這意味着下一個.then
將開始運行。 假設失敗了。 在這一點上,因為我們鏈接的承諾( promiseChain = promiseChain.then
),我們立即跳到第一.catch
(或者.then
用第二個參數)鏈,所有介入.then
小號得到完全沒有執行跳過。 或者,如果沒有catch
,那么這個承諾鏈就完成了。 無需休息; 這就是Promises的工作方式。
因此,如果僅在鏈的末尾添加.catch
,那就很好了。
關於“事件循環”的事情:我真的建議您觀看JSConf.Asia 2018的Jake Archibald:在循環中 。
也關於await
...聽起來好像對其工作方式有些困惑。 您只能在 async
函數中使用await
,因此您永遠無法通過單個await
完全阻止線程執行。 它的作用就像鏈接.then
一樣,只是語法糖。 因此,@ trincot絕對正確,您將使用該語法更加滿意。
這是一個備選的答案,它僅連續執行諾言,除非諾言被拒絕,然后將其終止。 這不使用await,但是應該給您一個大致的思路,如果沒有它,該怎么辦,但是該代碼的編寫速度也非常快,因此它不是最優化的代碼。
const x = function() { return new Promise(resolve => { resolve('it resolved ma!'); }); }; const y = function() { const self = this; return new Promise((resolve, reject) => { reject("reject"); }); }; const z = function() { const self = this; return new Promise((resolve, reject) => { resolve("never gets executed"); }); }; function runPromises(promises) { const results = []; let count = 0; const executePromise = i => { count++; return promises[i]() .then((response) => { results.push(response); if (count !== promises.length) { executePromise(count); } }) .catch((e) => { results.push(e); console.log("stop right now, thank you very much"); }); }; if (Array.isArray(promises)) { executePromise(count); } return results; } const results = runPromises([x, y, z]); console.log(results);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.