2016-06-18 29 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