2016-06-18 69 views
2

我一直在處理一個有趣的問題,在我的Typescript項目中(針對es6)。基本上,我希望能夠以某種不確定的順序快速定義許多不同系列的用戶輸入「頁面」,以及上一頁的結果對構建下一個「頁面」可能有沒有影響。Typescript async/await結構問題

因此,我將每個頁面視爲由函數構造的Promise(此處爲getPromise1()等),一旦用戶輸入完成,該函數就會解析爲結果。然後我使用async/await按順序創建頁面。

async process() { 
    let result1 = await this.getPromise1(); 

    let result2 = await this.getPromise2(result1.someData); 

    //etc... 

    this.commit(); 
} 

這個效果很好,但是我碰到了一個障礙。頁面順序可以通過用戶輸入在任何階段取消,因此構建需要在該點中止。問題是,在每一個階段檢查取消都變得非常乏味和不雅,而且對我來說,感覺非常強烈,就像錯誤的路要走。

async process() { 
    let result1 = await this.getPromise1(); 
    if (result1.cancelled) { 
     this.revert(); 
     return; 
    } 


    let result2 = await this.getPromise2(result1.someData); 
    if (result2.cancelled) { 
     this.revert(); 
     return; 
    } 

    //etc... 

    this.commit(); 
} 

我在哪裏出錯了?我對這種設置使用完全不正確的模式嗎?有沒有更好的方法來處理這種方法?或者是否真的沒有更好的辦法去做這樣的事情?

+0

僅供參考,'異步/ await'不是ES7的一部分。 –

回答

0

一個可能的解決辦法是讓你的「頁」 拒絕自己的承諾(即throw錯誤),這樣你就可以在你的process功能catch錯誤。

class App { 

    async process() { 
     try { 
      let result1 = await this.getPromise1(); 

      let result2 = await this.getPromise2(result1.someData); 

      //etc... 

      this.commit(); 
     } catch (e) { 
      this.revert(); 
     } 
    } 

    async getPromise1() { 
     return {someData: 'foo'}; 
    } 

    async getPromise2({someData}) { 
     throw new Error('cancelled'); 
    } 

} 
+0

我想到了這一點,但我不想將異常作爲運行該軟件的常規部分進行拋出/捕獲 - 它只是感覺錯誤,我認爲它會對性能產生重大影響。 – Daniel

+0

@Daniel同意,異常只應用於處理特殊情況,而不是用於「常規」控制流程。不幸的是,除了在OP中手動處理它之外,我想不出另一種方式。 : -/ –

0

由於這是一個順序,你總是在你的諾言測試cancelled,你可以

const seq: Prom[] = [this.getPromise1(), this.getPromise2(),...] 

for (let p of seq) { 
    const res = await p 
    if (res.cancelled) { 
     return this.revert() 
    } 
} 

或者創建一個所有你的承諾延長

interface Prom { 
    cancelled?: boolean 
} 

的接口,然後運行序列如果你的承諾是reject,而不是將結果設置爲cancelled(這是我所要做的),那麼你可以從fa金正日快Promise.all行爲:

try { 
    await Promise.all([this.getPromise1(), this.getPromise2(),...]) 
catch(e) { 
    //a promise was rejected 
} 

處理異常並不能真正使用await時避免。 所以,如果你不想處理異常,使用then

Promise.all([this.getPromise1(), this.getPromise2(),...]).then(
    () => { //success }, 
    (reason) => { // failure } 
) 
+0

感謝您的回答!不幸的是,這不允許我需要的非常重要的功能,即能夠將一個承諾的結果用作下一個承諾的輸入。至於異常處理,我不會處理異常,但是我想避免將它們拋入非常規情況。 – Daniel