簡體   English   中英

在for循環中打破Promise鏈

[英]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.

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