返回
揭开手写 Promise 与 async/await 的神秘面纱,为你点亮异步编程的曙光
前端
2023-12-09 05:18:11
在单线程运行机制下,javascript 引擎一经执行耗时过大的任务,必定会造成页面的阻塞,这显然会给用户体验带来负面影响。异步编程应运而生,试图解决阻塞难题。
Promise,javascript 内置的异步编程利器,它将回调嵌套的混乱转变成链式调用的优雅,极大地提升了异步编程的阅读性和可维护性。
手写 Promise 的实现过程,实乃探究异步编程核心奥义的必由之路。它能让你对 Promise 的工作原理有更为深入的了解。
class Promise {
constructor(executor) {
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
executor(this.resolve.bind(this), this.reject.bind(this));
}
resolve(value) {
if (this.state !== 'pending') {
return;
}
this.state = 'fulfilled';
this.value = value;
this.onFulfilledCallbacks.forEach(callback => callback(this.value));
}
reject(reason) {
if (this.state !== 'pending') {
return;
}
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach(callback => callback(this.reason));
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason; };
if (this.state === 'pending') {
this.onFulfilledCallbacks.push(onFulfilled);
this.onRejectedCallbacks.push(onRejected);
} else if (this.state === 'fulfilled') {
setTimeout(() => {
onFulfilled(this.value);
}, 0);
} else {
setTimeout(() => {
onRejected(this.reason);
}, 0);
}
return new Promise((resolve, reject) => {
this.then(value => {
try {
resolve(onFulfilled(value));
} catch (err) {
reject(err);
}
}, reason => {
try {
resolve(onRejected(reason));
} catch (err) {
reject(err);
}
});
});
}
}
掌握了手写 Promise 的精髓,你已经成功踏出了异步编程的第一步。
async/await 作为 ES2017 引入的语法糖,它将异步编程的语法又向前推进了一步,让异步编程的操作看起来就像同步操作一样,极大地提高了异步编程的简洁性和易读性。
async function asyncFunction() {
const value = await promise;
return value;
}
使用 async/await 时,你需要注意以下几点:
- async 函数总是返回一个 Promise。
- await 只能用在 async 函数中。
- await 后面跟的是一个 Promise 对象。
- await 会暂停 async 函数的执行,直到 Promise 对象的状态变为 resolved 或 rejected。
- await 会将 Promise 对象的状态结果作为返回值。
通过手写 Promise 和 async/await,你已经掌握了 javascript 异步编程的精髓,你的编程之路必将更上一层楼!