2017-09-16 40 views
0

我有一個保存功能,它的行爲是異步的,因此我使用承諾。一個主要的保存事件會進入並且一次只附加一個thencatch處理程序。對於我的代碼示例,這將發生在importantSave方法中。現在,可能會有其他任何其他保存調用稍後調用,並且您可以參考sideSave方法。是否可以重寫已聲明的Promise鏈?

有沒有一種方法,使在importantSave方法等待的thencatch處理程序所有的側面可以節省解決/拒絕被調用之前,即使他們設立第一?

例如,我有以下代碼:

class Adapter { 
    promise; 
    next_attempt; 

    attempt() { 
     if (this.promise && this.promise.isPending()) { 
      this.next_attempt = this.attempt.bind(this); 
      return this.promise.then(()=> { 
       if (this.next_attempt) { 
        return this.next_attempt(); 
       } 
      }); 
     } else { 
      this.promise = new Promise(resolve=> { 
       setTimeout(resolve, 3000); 
      }); 

      return this.promise; 
     } 
    } 
} 
const adapter = new Adapter(); 

function importantSave() { 
    adapter.attempt() 
     .then(()=> { 
      console.log('Hello from the important save!'); 
     }); 
} 

function sideSave() { 
    adapter.attempt() 
     .then(()=> { 
      console.log('Hello from the side save!'); 
     }); 
} 

// the important save which sets up its then and catches, but wants to be called after all have finished 
importantSave(); 

// any number of side saves, but will only be called with the last side save 
sideSave(); 
sideSave(); 
sideSave(); 

有沒有辦法來改變這種做法,如果importantSave的then在sideSave調用任何thens後居然跑?我真實世界的例子會在每次調用之間延遲3次調用save函數,並且只會在3次失敗時纔會拒絕。如果另一個保存呼叫發生在所有3次失敗之前發生,我希望最新呼叫成爲「next_attempt」,覆蓋任何其他嘗試在第一個呼叫仍在等待時保存。如果原始呼叫保存失敗,但其中一個「sideSave」呼叫通過,我希望importantSave得到滿足,從而落入當時,而不是原來的失敗。

+0

請注意,您將覆蓋'this.next_attempt'時,它已經有一個值,你永遠清除它。還要注意,讓代碼依賴於類似'isPending()'的東西是不好的做法。除了使用諸如'then'之類的東西或派生方法之外,人們永遠不需要檢查承諾的狀態。 – trincot

回答

1

這是通常的做法,與Promise.all

添加你需要在一個陣列來解決,並把它作爲參數的所有承諾:

Promise.all([importantSave(), sideSave(), sideSave(), sideSave()]).then(_ => { 
    console.log('all done'); 
}); 

當然你可以動態生成數組:

var arr = [importantSave()]; 

arr.push(sideSave()); 
arr.push(sideSave()); 
arr.push(sideSave()); 

Promise.all(arr).then(_ => { 
    console.log('all done'); 
}); 

如果你只需要一個履行,然後使用這些承諾的對立面。你可以使用一個輔助函數爲:

const invert = p => p.then(resp => { throw resp }).catch(err => err); 

該函數返回一個承諾,當其參數滿足會拒絕,反之亦然。

現在你可以這樣做:

var arr = [importantSave()]; 

arr.push(sideSave()); 
arr.push(sideSave()); 
arr.push(sideSave()); 

invert(Promise.all(arr.map(invert))).then(_ => { 
    console.log('one done'); 
}); 
+0

這不起作用。也許我的描述不容易理解,但'sideSaves'動態地來自我的代碼的不同區域。在連接原始'then'之前,您無法知道將會保存多少次保存。想象這一點,想象下面的代碼: '''var arr = [importantSave()]; ()=> { \t arr.push(sideSave()); },1000); ()=> { \t arr.push(sideSave()); },2000); Promise.all(arr).then(_ => { } \t console。日誌('全部完成'); Promise.all將直接在importantSave之後解析,但會忽略窗口超時中的sideSaves。 – jas7457

+0

是的,你當然應該忽視解決的承諾,因爲你不知道你還會添加多少。你真正的承諾,成爲Promise.all。你的問題是模棱兩可的,因爲你說你想等待的一方,但也表示你想盡快解決問題。 – trincot

+0

你需要什麼?要重試一次操作3次,只有在全部失敗時才放棄?你寫*只會拒絕,如果所有3失敗*,那麼爲什麼等待所有時,你有履行? – trincot

相關問題