从Promise到async/await:手写实现异步编程核心机制全解析
2025.09.19 12:47浏览量:3简介:本文通过手写实现Promise核心方法、Generator迭代器及async/await语法糖,深度解析JavaScript异步编程的底层原理,帮助开发者掌握异步控制流的本质逻辑。
从Promise到async/await:手写实现异步编程核心机制全解析
异步编程是JavaScript开发的核心能力,而Promise、Generator和async/await构成了现代异步编程的三大支柱。本文将通过手写实现这些核心机制,深入解析其工作原理,帮助开发者建立完整的异步编程知识体系。
一、Promise核心机制手写实现
1.1 Promise基础结构
Promise本质是一个带有状态机的对象,包含三种状态:pending、fulfilled和rejected。手写实现需要重点处理状态变更的不可逆性。
class MyPromise {constructor(executor) {this.state = 'pending'; // 初始状态this.value = undefined; // 成功值this.reason = undefined; // 失败原因this.onFulfilledCallbacks = []; // 成功回调队列this.onRejectedCallbacks = []; // 失败回调队列const resolve = (value) => {if (this.state === 'pending') {this.state = 'fulfilled';this.value = value;this.onFulfilledCallbacks.forEach(fn => fn());}};const reject = (reason) => {if (this.state === 'pending') {this.state = 'rejected';this.reason = reason;this.onRejectedCallbacks.forEach(fn => fn());}};try {executor(resolve, reject);} catch (err) {reject(err);}}}
1.2 then方法实现
then方法是Promise的核心,需要处理链式调用和异步回调:
then(onFulfilled, onRejected) {// 参数默认值处理onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err; };const promise2 = new MyPromise((resolve, reject) => {if (this.state === 'fulfilled') {setTimeout(() => {try {const x = onFulfilled(this.value);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}}, 0);} else if (this.state === 'rejected') {setTimeout(() => {try {const x = onRejected(this.reason);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}}, 0);} else if (this.state === 'pending') {this.onFulfilledCallbacks.push(() => {setTimeout(() => {try {const x = onFulfilled(this.value);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}}, 0);});this.onRejectedCallbacks.push(() => {setTimeout(() => {try {const x = onRejected(this.reason);resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}}, 0);});}});return promise2;}
1.3 解析Promise链式调用
关键在于resolvePromise函数的实现,它处理then方法返回值的各种情况:
function resolvePromise(promise2, x, resolve, reject) {// 防止循环引用if (promise2 === x) {return reject(new TypeError('Chaining cycle detected for promise'));}let called = false;// 处理x为对象或函数的情况if (x !== null && (typeof x === 'object' || typeof x === 'function')) {try {const then = x.then;if (typeof then === 'function') {then.call(x,y => {if (called) return;called = true;resolvePromise(promise2, y, resolve, reject);},r => {if (called) return;called = true;reject(r);});} else {resolve(x);}} catch (e) {if (called) return;called = true;reject(e);}} else {resolve(x);}}
二、Generator函数实现原理
2.1 Generator基础实现
Generator的核心是状态机和迭代器协议:
function* myGenerator() {yield 1;yield 2;return 3;}// 手写实现类似功能function createIterator(generatorFn) {const iterator = {next: function(value) {// 实际实现需要维护状态和上下文// 这里简化展示流程if (!this._init) {this._context = generatorFn.call(this);this._init = true;}const result = this._context.next(value);return {value: result.value,done: result.done};},_init: false,_context: null};return iterator;}
2.2 迭代器协议实现
完整的迭代器需要实现[Symbol.iterator]方法:
function* countUpTo(max) {let count = 1;while (count <= max) {yield count++;}}// 转换为可迭代对象const iterable = {[Symbol.iterator]: function* () {yield* countUpTo(3);}};// 手写等效实现const manualIterable = {[Symbol.iterator]: function() {let count = 1;const max = 3;return {next: function() {if (count <= max) {return { value: count++, done: false };} else {return { done: true };}}};}};
三、async/await语法糖解析
3.1 async函数本质
async函数实际上是Generator函数的语法糖,编译器会将其转换为状态机:
async function fetchData() {try {const res = await fetch('/api/data');const data = await res.json();return data;} catch (err) {console.error(err);}}// 等效的Generator实现function fetchDataGen() {return regeneratorRuntime.wrap(function fetchDataGen$(_context) {while (1) {switch (_context.prev = _context.next) {case 0:_context.prev = 0;_context.next = 3;return regeneratorRuntime.awrap(fetch('/api/data'));// ...其余实现}}}, fetchDataGen);}
3.2 手动实现async/await模式
通过Generator+Promise可以手动实现类似async/await的效果:
function run(generatorFn) {const generator = generatorFn();function handle(result) {if (result.done) return Promise.resolve(result.value);return Promise.resolve(result.value).then(res => handle(generator.next(res)),err => handle(generator.throw(err)));}try {return handle(generator.next());} catch (err) {return Promise.reject(err);}}// 使用示例run(function* () {try {const res = yield fetch('/api/data');const data = yield res.json();console.log(data);} catch (err) {console.error(err);}});
四、实际应用与最佳实践
4.1 错误处理模式
// Promise错误处理fetchData().then(data => process(data)).catch(err => handleError(err));// async/await错误处理async function safeFetch() {try {const data = await fetchData();process(data);} catch (err) {handleError(err);}}
4.2 并行控制优化
// Promise.all实现function myPromiseAll(promises) {return new Promise((resolve, reject) => {const results = [];let completed = 0;promises.forEach((promise, index) => {Promise.resolve(promise).then(value => {results[index] = value;completed++;if (completed === promises.length) {resolve(results);}}).catch(reject);});});}// async/await中的并行优化async function fetchAll() {const [user, posts] = await Promise.all([fetchUser(),fetchPosts()]);// ...}
五、性能优化与调试技巧
5.1 微任务与宏任务调度
// 验证微任务优先级console.log('script start');setTimeout(() => {console.log('setTimeout');}, 0);new Promise((resolve) => {console.log('Promise executor');resolve();console.log('Promise executor after resolve');}).then(() => {console.log('Promise then');});console.log('script end');// 输出顺序:// script start// Promise executor// Promise executor after resolve// script end// Promise then// setTimeout
5.2 调试async/await
// 使用生成器函数调试function* debugGen() {console.log('Before yield 1');yield 1;console.log('Between yield 1 and 2');yield 2;console.log('After yield 2');}const gen = debugGen();console.log(gen.next()); // 执行到第一个yieldconsole.log(gen.next()); // 执行到第二个yieldconsole.log(gen.next()); // 执行完毕
六、总结与展望
通过手写实现Promise、Generator和async/await的核心机制,我们深入理解了JavaScript异步编程的底层原理。这些实现不仅帮助我们更好地使用这些特性,也为解决复杂异步问题提供了理论基础。在实际开发中,建议:
- 优先使用async/await提高代码可读性
- 合理使用Promise.all等并行方法优化性能
- 注意错误处理的完整性
- 在需要精细控制的场景考虑使用Generator
随着JavaScript生态的发展,异步编程模式仍在不断演进,但掌握这些核心原理将使开发者能够更快适应新的异步编程范式。

发表评论
登录后可评论,请前往 登录 或 注册