从Promise到async/await:手写实现异步编程核心机制全解析
2025.09.19 12:47浏览量:0简介:本文通过手写实现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()); // 执行到第一个yield
console.log(gen.next()); // 执行到第二个yield
console.log(gen.next()); // 执行完毕
六、总结与展望
通过手写实现Promise、Generator和async/await的核心机制,我们深入理解了JavaScript异步编程的底层原理。这些实现不仅帮助我们更好地使用这些特性,也为解决复杂异步问题提供了理论基础。在实际开发中,建议:
- 优先使用async/await提高代码可读性
- 合理使用Promise.all等并行方法优化性能
- 注意错误处理的完整性
- 在需要精细控制的场景考虑使用Generator
随着JavaScript生态的发展,异步编程模式仍在不断演进,但掌握这些核心原理将使开发者能够更快适应新的异步编程范式。
发表评论
登录后可评论,请前往 登录 或 注册