我一直在处理我的Typescript项目中的一个有趣的问题(针对es6)。基本上,我希望能够以某种不确定的顺序快速定义许多不同系列的用户输入“页面”,并且前一页的结果可能会或可能不会对下一个“页面”的构造产生影响。
因此,我将每个页面视为由函数(此处为getPromise1()
等)构造的Promise,一旦用户输入完成,该函数将解析为结果。然后我使用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 :(得分:0)
一种可能的解决方案可能是让您的“网页”拒绝他们的承诺(即throw
错误),以便catch
process
出现错误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');
}
}
功能。
a
答案 1 :(得分:0)
由于这是一个序列而你总是在你的承诺上测试cancelled
,你可以创建一个你承诺扩展的接口
interface Prom {
cancelled?: boolean
}
然后运行序列
const seq: Prom[] = [this.getPromise1(), this.getPromise2(),...]
for (let p of seq) {
const res = await p
if (res.cancelled) {
return this.revert()
}
}
或者,如果您承诺reject
而不是将结果设置为cancelled
(我会这样做),您可以从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 }
)