TypeScript async、 await、Promise
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/async_function
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/await
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Using_promises
实现延时:
// LayaAir3.x 中测试
const { regClass, property } = Laya;
@regClass()
export class Test extends Laya.Script {
onStart() {
this.delay(1000);
// 先输出1,1秒后输出2
// 输出:
// 1
// 2
}
private sleep(ms: number): Promise<any> {
return new Promise(resolve => setTimeout(resolve, ms));
}
private async delay(ms: number): Promise<any> {
console.log("1");
await this.sleep(ms);
console.log("2");
}
}
延时执行 for循环:
// LayaAir3.x 中测试
const { regClass, property } = Laya;
@regClass()
export class Test extends Laya.Script {
onStart() {
this.handler(1000);
// 输出
// start
// 一秒后
// 0
// 一秒后
// 1
// 一秒后
// 2
// end
}
private sleep(ms: number): Promise<any> {
return new Promise(resolve => setTimeout(resolve, ms));
}
private async handler(ms:number): Promise<any> {
console.log("start");
for (let i = 0; i < 3; i++) {
await this.sleep(ms);
console.log(i);
}
console.log("end");
}
}
Promise
例:使用 Promise 代替传参式的完成回调
// LayaAir3.x 中测试
const { regClass, property } = Laya;
@regClass()
export class TestPromise extends Laya.Script {
public onAwake(): void {
console.log("start");
this.delay().then((value: any) => {
console.log("end", value);
});
/*output:
start
...3秒后...
end hello
*/
}
private delay(): Promise<any> {
return new Promise((resolve: (value: any) => void, reject: (reason?: any) => void) => {
setTimeout(() => {
resolve("hello");
}, 3000);
});
}
}
多个缓动
// LayaAir3.x 中测试
const { regClass, property } = Laya;
@regClass()
export class TestPromiseTweenComplete extends Laya.Script {
public onAwake(): void {
this.startTween();
/*output:
a
// ...1秒后...
b
// ...1秒后...
c
*/
}
private async startTween(): Promise<any> {
console.log("a");
await this.tween0();
console.log("b");
await this.tween1();
console.log("c");
}
private tween0(): Promise<any> {
return new Promise((resolve: (value: any) => void, reject: (reason?: any) => void) => {
Laya.Tween.create(this.owner).duration(1000).to("x", 100).then(tweener => {
resolve(tweener);
}, this);
});
}
private tween1(): Promise<any> {
return new Promise((resolve: (value: any) => void, reject: (reason?: any) => void) => {
Laya.Tween.create(this.owner).duration(1000).to("y", 100).then(tweener => {
resolve(tweener);
}, this);
});
}
}
Promise在TypeScript中是一个对象,它代表了一个异步操作的最终结果。一个Promise对象可以处于以下三种状态之一:
Pending(进行中): 初始状态,既不是成功,也不是失败状态。
Fulfilled(已成功): 意味着操作成功完成。
Rejected(已失败): 意味着操作失败。
// 缺省变量的类型,any 根据调用 resolve, reject 时传入的参数的类型进行变化
// promise: Promise<any>
// resolve: (value: any) => void
// reject: (reason?: any) => void
// 创建一个新的Promise对象
let promise = new Promise((resolve, reject) => {
// 异步操作的代码
if (/* 异步操作成功 */) {
resolve(value); // 成功时调用resolve函数
} else {
reject(error); // 失败时调用reject函数
}
});
Promise 的错误处理
通过.then()方法,可以指定fulfilled状态和rejected状态的回调函数,这些回调函数可以返回一个新的Promise,从而形成链式调用。
promise.then((value) => {
// 成功时执行的代码
}).catch((error) => {
// 失败时执行的代码
});
promise.then((value) => {
throw new Error('Something went wrong');
}).catch((error) => {
// 捕获前面.then()中抛出的错误
});
Promise的静态方法
Promise还提供了一些静态方法,如Promise.all()和Promise.race(),它们可以用于处理多个Promise的组合.
// 等待所有Promise完成
Promise.all([promise1, promise2]).then((values) => {
// 所有Promise都成功时执行的代码
});
// 竞赛,哪个Promise先完成就使用哪个Promise的结果
Promise.race([promise1, promise2]).then((value) => {
// 最先完成的Promise的结果
});
Promise的类型推断
// TypeScript能够推断出res的类型为number
Promise.resolve(123).then((res) => {
// res的类型被推断为number
});
Promise 返回值测试
// LayaAir3.x 中测试
const { regClass, property } = Laya;
@regClass()
export class TestPromiseReturn extends Laya.Script {
private resolvePromise(): Promise<any> {
return new Promise((resolve: (value: any) => void, reject: (reason?: any) => void) => {
setTimeout(() => {
resolve("resolve promise");
}, 1000);
});
}
private rejectPromise(): Promise<any> {
return new Promise((resolve: (value: any) => void, reject: (reason?: any) => void) => {
setTimeout(() => {
reject("reject promise");
}, 1000);
});
}
public onAwake(): void {
const pa = this.resolvePromise();
const pb = this.resolvePromise().then();
const pc = this.resolvePromise().catch();
console.log("pa", pa);
console.log("pb", pb);
console.log("pc", pc);
/* output:
pa Promise {<pending>}[[Prototype]]: Promise[[PromiseState]]: "fulfilled"[[PromiseResult]]: "resolve promise"
pb Promise {<pending>}[[Prototype]]: Promise[[PromiseState]]: "fulfilled"[[PromiseResult]]: "resolve promise"
pc Promise {<pending>}[[Prototype]]: Promise[[PromiseState]]: "fulfilled"[[PromiseResult]]: "resolve promise"
*/
const pb1 = this.resolvePromise().then(res => { });
const pb2 = this.resolvePromise().then(res => { }, err => { });
const pb3 = this.resolvePromise().then(res => { }, err => { return err; });
console.log("pb1", pb1);
console.log("pb2", pb2);
console.log("pb3", pb3);
/* output:
pb1 Promise[[Prototype]]: Promise[[PromiseState]]: "fulfilled"[[PromiseResult]]: undefined
pb2 Promise[[Prototype]]: Promise[[PromiseState]]: "fulfilled"[[PromiseResult]]: undefined
pb3 Promise[[Prototype]]: Promise[[PromiseState]]: "fulfilled"[[PromiseResult]]: undefined
*/
const pb4 = this.resolvePromise().then(res => { return res; });
const pb5 = this.resolvePromise().then(res => { return res; }, err => { });
const pb6 = this.resolvePromise().then(res => { return res; }, err => { return err; });
console.log("pb4", pb4);
console.log("pb5", pb5);
console.log("pb6", pb6);
/* output:
pb4 Promise[[Prototype]]: Promise[[PromiseState]]: "fulfilled"[[PromiseResult]]: "resolve promise"
pb5 Promise[[Prototype]]: Promise[[PromiseState]]: "fulfilled"[[PromiseResult]]: "resolve promise"
pb6 Promise[[Prototype]]: Promise[[PromiseState]]: "fulfilled"[[PromiseResult]]: "resolve promise"
*/
}
public onEnable(): void {
const p1 = this.rejectPromise();
const p2 = this.rejectPromise().then();
const p3 = this.rejectPromise().catch();
console.log("p1", p1);
console.log("p2", p2);
console.log("p3", p3);
/* output:
p1 Promise {<pending>}[[Prototype]]: Promise[[PromiseState]]: "rejected"[[PromiseResult]]: "reject promise"
p2 Promise {<pending>}[[Prototype]]: Promise[[PromiseState]]: "rejected"[[PromiseResult]]: "reject promise"
p3 Promise {<pending>}[[Prototype]]: Promise[[PromiseState]]: "rejected"[[PromiseResult]]: "reject promise"
*/
const p11 = this.rejectPromise().then(res => { }, err => { });
const p22 = this.rejectPromise().then(res => { }, err => { return err; });
console.log("p11", p11);
console.log("p22", p22);
/* output:
p11 Promise {<pending>}[[Prototype]]: Promise[[PromiseState]]: "fulfilled"[[PromiseResult]]: undefined
p22 Promise {<pending>}[[Prototype]]: Promise[[PromiseState]]: "fulfilled"[[PromiseResult]]: "reject promise"
*/
const p33 = this.rejectPromise().catch(err => { });
const p44 = this.rejectPromise().catch(err => { return err; });
console.log("p33", p33);
console.log("p44", p44);
/* output:
p33 Promise {<pending>}[[Prototype]]: Promise[[PromiseState]]: "fulfilled"[[PromiseResult]]: undefined
p44 Promise {<pending>}[[Prototype]]: Promise[[PromiseState]]: "fulfilled"[[PromiseResult]]: "reject promise"
*/
}
public onStart(): void {
this.resolvePromise().then(res => { }).then(res => { console.log("res", res); }); // 1秒后,输出:res undefined
this.resolvePromise().then(res => { return res; }).then(res => { console.log("res", res); }); // 1秒后,输出:res resolve promise
this.rejectPromise()
.then(res => { return res; }, err => { }) // 定义了 onrejected 回调,在赋值到变量或链式调用时,将不再被执行
.then(res => { return res; }, err => { console.log("err0", err); }); // 无输出
this.rejectPromise()
.then(res => { return res; }, err => { return err; }) // 定义了 onrejected 回调,在赋值到变量或链式调用时,将不再被执行
.then(res => { return res; }, err => { console.log("err1", err); }); // 无输出
this.rejectPromise()
.then(res => { return res; }) //
.then(res => { return res; }, err => { console.log("err2", err); }); // 1秒后,输出:err2 reject promise
this.rejectPromise().catch().catch(err => { console.log("err3", err); }); // 1秒后,输出:err3 reject promise
this.rejectPromise()
.catch(err => { }) // 定义了 onrejected 回调,在赋值到变量或链式调用时,将不再被执行
.catch(err => { console.log("err4", err); }); // 无输出
this.rejectPromise()
.catch(err => { return err; }) // 定义了 onrejected 回调,在赋值到变量或链式调用时,将不再被执行
.catch(err => { console.log("err5", err); }); // 无输出
}
}
Promise await 返回值测试
// LayaAir3.x 中测试
const { regClass, property } = Laya;
@regClass()
export class TestPromiseAwaitReturn extends Laya.Script {
public createSpriteAsync(): Promise<Laya.Sprite> {
return new Promise((resolve, reject) => {
setTimeout(() => {
const sprite = new Laya.Sprite();
resolve(sprite);
}, 1000);
});
}
public createSpriteAsyncErr(): Promise<Laya.Sprite> {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error("create sprite error"));
}, 1000);
});
}
public async onAwake() {
const promise: Promise<Laya.Sprite> = this.createSpriteAsync();
console.log("promise:", promise); // promise: Promise {<pending>}[[Prototype]]: Promise[[PromiseState]]: "fulfilled"[[PromiseResult]]: Sprite
const sprite: Laya.Sprite = await this.createSpriteAsync();
console.log("sprite:", sprite); // 1秒后,输出:sprite: Sprite {_bits: 9, _reactiveBits: 16, _hideFlags: 0, _parent: null, _destroyed: false, …}
const promise1: Promise<Laya.Sprite> = this.createSpriteAsyncErr();
console.log("promise1:", promise1); // promise1: Promise {<pending>}[[Prototype]]: Promise[[PromiseState]]: "rejected"[[PromiseResult]]: Error: create sprite error at ...
const sprite1: Laya.Sprite = await this.createSpriteAsyncErr();
// 因报错而中止,此处以下的所有代码不会执行
console.log("sprite1:", sprite1);
}
}