【发布时间】:2016-08-05 18:50:24
【问题描述】:
如何将 async/await 代码 (Typescript + es6 target) 转换为使用链式 Promise.then()?
例如:
function mockDelay<T>(getValue:()=>T): Promise<T> {
return new Promise<T>(resolve=>setTimeout(()=>resolve(getValue()), 10));
}
// Assume blackbox implementation
class Service {
constructor(private i=1, private callCount=0){}
opA() : Promise<number> {
this.callCount++;
return mockDelay(()=>this.i+=1);
}
opB(value:number) : Promise<number> {
this.callCount++;
return mockDelay(()=>this.i+=value);
}
opC(): Promise<number> {
return mockDelay(()=>this.i+=2);
}
isA(): Promise<boolean> { return mockDelay(()=>this.callCount%2===0); }
isC(): Promise<boolean> { return mockDelay(() =>true); }
}
// Convert this async/await code to using chained Promises
async function asyncVersion(): Promise<string[]>{
let expected:string[] = [];
let lib = new Service();
let sum = 20;
let lastValue = 0;
while (sum > 0) {
expected.push(`${sum} left`);
if (await lib.isA())
{
expected.push("Do A()");
lastValue = await lib.opA();
sum -= lastValue;
}
else
{
expected.push("Do B()");
lastValue = await lib.opB(lastValue);
sum -= lastValue*3;
if (await lib.isC()) {
expected.push("Do C()");
sum += await lib.opC();
}
}
}
expected.push("All completed!");
return expected;
};
function chainPromiseVersion(): Promise<string[]>{
// How to convert the asyncVersion() to using chained promises?
return Promise.resolve([]);
}
// Compare results
// Currently running asyncVersion() twice to ensure call results are consistent/no side effects
// Replace asyncVersion() with chainPromiseVersion()
Promise.all([asyncVersion(), asyncVersion() /*chainPromiseVersion()*/])
.then(result =>{
let expected = result[0];
let actual = result[1];
if (expected.length !== actual.length)
throw new Error(`Length: expected ${expected.length} but was ${actual.length}`);
for(let i=0; i<expected.length; i++) {
if (expected[i] !== actual[i]){
throw new Error(`Expected ${expected[i]} but was ${actual[i]}`);
}
}
})
.then(()=>console.log("Test completed"))
.catch(e => console.log("Error: " + e));
我知道我可以使用 Babel (Github example) 将 es6 代码转换为 es5。
这个问题是关于手动重写 async/await 代码以使用链式 Promise。
我可以像下面这样转换简单的例子。
// Async/Await
(async function(){
for (let i=0; i<5; i++){
let result = await mockDelay(()=>"Done " + i);
console.log(result);
}
console.log("All done");
})();
// Chained Promises
(function(){
let chain = Promise.resolve(null);
for (let i=0; i<5; i++){
chain = chain
.then(()=>mockDelay(()=>"Done " + i))
.then(result => console.log(result));
}
chain.then(()=>console.log("All done"));
})();
但不知道如何转换上面的示例,其中:
- 受承诺结果影响的循环条件
- 必须一个接一个地执行(不是
Promise.all())
【问题讨论】:
-
你为什么要这样做?
-
学习如何。如果我的最终目标只是让 async/await 代码针对 es5,那么我已经在使用 Babel 进行编译了。
标签: typescript promise async-await