第2章:高级异步编程
📖 本章概述
异步编程是现代JavaScript开发的核心技能。本章将深入探讨Promise的实现原理、async/await的底层机制、Generator函数的高级用法,以及如何优雅地处理复杂的异步场景。
🎯 学习目标
完成本章学习后,你将能够:
- 理解Promise的完整实现原理
- 掌握async/await的底层转换机制
- 熟练使用Generator进行异步控制
- 实现高级的异步模式和并发控制
- 优雅地处理异步错误和取消操作
🔄 Promise深度解析
Promise状态机制
Promise有三种状态,状态转换是不可逆的:
javascript
// Promise状态转换
const promise = new Promise((resolve, reject) => {
// pending状态
console.log('Promise创建,状态:pending');
setTimeout(() => {
if (Math.random() > 0.5) {
resolve('成功'); // pending -> fulfilled
} else {
reject('失败'); // pending -> rejected
}
}, 1000);
});
promise
.then(value => console.log('fulfilled:', value))
.catch(error => console.log('rejected:', error));
手写Promise实现
javascript
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 (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason; };
const promise2 = new MyPromise((resolve, reject) => {
if (this.state === 'fulfilled') {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
this.resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
} else if (this.state === 'rejected') {
setTimeout(() => {
try {
const x = onRejected(this.reason);
this.resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
} else if (this.state === 'pending') {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
this.resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason);
this.resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
});
}
});
return promise2;
}
resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('循环引用'));
}
if (x instanceof MyPromise) {
x.then(resolve, reject);
} else {
resolve(x);
}
}
catch(onRejected) {
return this.then(null, onRejected);
}
static resolve(value) {
return new MyPromise(resolve => resolve(value));
}
static reject(reason) {
return new MyPromise((resolve, reject) => reject(reason));
}
static all(promises) {
return new MyPromise((resolve, reject) => {
const results = [];
let completedCount = 0;
promises.forEach((promise, index) => {
MyPromise.resolve(promise).then(value => {
results[index] = value;
completedCount++;
if (completedCount === promises.length) {
resolve(results);
}
}, reject);
});
});
}
static race(promises) {
return new MyPromise((resolve, reject) => {
promises.forEach(promise => {
MyPromise.resolve(promise).then(resolve, reject);
});
});
}
}
Promise高级用法
javascript
// Promise.allSettled实现
Promise.myAllSettled = function(promises) {
return Promise.all(
promises.map(promise =>
Promise.resolve(promise)
.then(value => ({ status: 'fulfilled', value }))
.catch(reason => ({ status: 'rejected', reason }))
)
);
};
// 使用示例
const promises = [
Promise.resolve(1),
Promise.reject('error'),
Promise.resolve(3)
];
Promise.myAllSettled(promises).then(results => {
console.log(results);
// [
// { status: 'fulfilled', value: 1 },
// { status: 'rejected', reason: 'error' },
// { status: 'fulfilled', value: 3 }
// ]
});
🔄 async/await深度解析
async/await转换原理
async/await本质上是Generator + Promise的语法糖:
javascript
// async/await代码
async function fetchData() {
try {
const response = await fetch('/api/data');
const data = await response.json();
return data;
} catch (error) {
console.error('Error:', error);
throw error;
}
}
// 等价的Generator实现
function* fetchDataGenerator() {
try {
const response = yield fetch('/api/data');
const data = yield response.json();
return data;
} catch (error) {
console.error('Error:', error);
throw error;
}
}
// 自动执行器
function runGenerator(generatorFn) {
return new Promise((resolve, reject) => {
const generator = generatorFn();
function step(nextFn) {
let next;
try {
next = nextFn();
} catch (error) {
return reject(error);
}
if (next.done) {
return resolve(next.value);
}
Promise.resolve(next.value).then(
value => step(() => generator.next(value)),
error => step(() => generator.throw(error))
);
}
step(() => generator.next());
});
}
// 使用
runGenerator(fetchDataGenerator).then(data => console.log(data));
错误处理最佳实践
javascript
// 统一错误处理
class AsyncErrorHandler {
static async safeExecute(asyncFn, fallback = null) {
try {
return await asyncFn();
} catch (error) {
console.error('Async operation failed:', error);
return fallback;
}
}
static async retry(asyncFn, maxRetries = 3, delay = 1000) {
for (let i = 0; i < maxRetries; i++) {
try {
return await asyncFn();
} catch (error) {
if (i === maxRetries - 1) throw error;
await new Promise(resolve => setTimeout(resolve, delay * Math.pow(2, i)));
}
}
}
}
// 使用示例
async function unreliableAPI() {
if (Math.random() < 0.7) {
throw new Error('API调用失败');
}
return { data: 'success' };
}
// 安全执行
const result = await AsyncErrorHandler.safeExecute(
unreliableAPI,
{ data: 'fallback' }
);
// 重试机制
const retryResult = await AsyncErrorHandler.retry(unreliableAPI, 3, 500);
⚡ Generator高级应用
Generator基础与迭代器协议
javascript
// Generator函数基础
function* numberGenerator() {
let index = 0;
while (true) {
yield index++;
}
}
const gen = numberGenerator();
console.log(gen.next()); // { value: 0, done: false }
console.log(gen.next()); // { value: 1, done: false }
// 双向通信
function* twoWayGenerator() {
const input1 = yield 'First yield';
console.log('Received:', input1);
const input2 = yield 'Second yield';
console.log('Received:', input2);
return 'Generator finished';
}
const twoWayGen = twoWayGenerator();
console.log(twoWayGen.next()); // { value: 'First yield', done: false }
console.log(twoWayGen.next('Hello')); // { value: 'Second yield', done: false }
console.log(twoWayGen.next('World')); // { value: 'Generator finished', done: true }
异步Generator
javascript
// 异步Generator
async function* asyncDataStream() {
for (let i = 0; i < 5; i++) {
await new Promise(resolve => setTimeout(resolve, 1000));
yield `Data chunk ${i}`;
}
}
// 使用for-await-of消费异步Generator
async function consumeAsyncStream() {
for await (const chunk of asyncDataStream()) {
console.log('Received:', chunk);
}
}
consumeAsyncStream();
Generator实现协程
javascript
// 使用Generator实现简单的协程调度器
class TaskScheduler {
constructor() {
this.tasks = [];
this.running = false;
}
addTask(generatorFn) {
this.tasks.push(generatorFn());
}
async run() {
if (this.running) return;
this.running = true;
while (this.tasks.length > 0) {
const activeTasks = [...this.tasks];
this.tasks = [];
for (const task of activeTasks) {
const { value, done } = task.next();
if (!done) {
if (value instanceof Promise) {
await value;
}
this.tasks.push(task);
}
}
// 让出控制权
await new Promise(resolve => setTimeout(resolve, 0));
}
this.running = false;
}
}
// 使用示例
function* task1() {
console.log('Task 1 - Step 1');
yield new Promise(resolve => setTimeout(resolve, 100));
console.log('Task 1 - Step 2');
yield;
console.log('Task 1 - Step 3');
}
function* task2() {
console.log('Task 2 - Step 1');
yield;
console.log('Task 2 - Step 2');
yield new Promise(resolve => setTimeout(resolve, 50));
console.log('Task 2 - Step 3');
}
const scheduler = new TaskScheduler();
scheduler.addTask(task1);
scheduler.addTask(task2);
scheduler.run();
🚦 并发控制与限流
并发限制器
javascript
class ConcurrencyLimiter {
constructor(limit) {
this.limit = limit;
this.running = 0;
this.queue = [];
}
async execute(asyncFn) {
return new Promise((resolve, reject) => {
this.queue.push({
asyncFn,
resolve,
reject
});
this.process();
});
}
async process() {
if (this.running >= this.limit || this.queue.length === 0) {
return;
}
this.running++;
const { asyncFn, resolve, reject } = this.queue.shift();
try {
const result = await asyncFn();
resolve(result);
} catch (error) {
reject(error);
} finally {
this.running--;
this.process();
}
}
}
// 使用示例
const limiter = new ConcurrencyLimiter(3);
const tasks = Array.from({ length: 10 }, (_, i) =>
() => new Promise(resolve => {
console.log(`Task ${i} started`);
setTimeout(() => {
console.log(`Task ${i} completed`);
resolve(i);
}, Math.random() * 2000);
})
);
// 并发执行,但最多同时3个
Promise.all(tasks.map(task => limiter.execute(task)))
.then(results => console.log('All tasks completed:', results));
请求去重与缓存
javascript
class RequestDeduplicator {
constructor() {
this.cache = new Map();
this.pending = new Map();
}
async request(key, requestFn, ttl = 60000) {
// 检查缓存
if (this.cache.has(key)) {
const { data, timestamp } = this.cache.get(key);
if (Date.now() - timestamp < ttl) {
return data;
}
this.cache.delete(key);
}
// 检查是否有相同请求正在进行
if (this.pending.has(key)) {
return this.pending.get(key);
}
// 发起新请求
const promise = requestFn()
.then(data => {
this.cache.set(key, { data, timestamp: Date.now() });
this.pending.delete(key);
return data;
})
.catch(error => {
this.pending.delete(key);
throw error;
});
this.pending.set(key, promise);
return promise;
}
}
// 使用示例
const deduplicator = new RequestDeduplicator();
async function fetchUserData(userId) {
return deduplicator.request(
`user:${userId}`,
() => fetch(`/api/users/${userId}`).then(res => res.json()),
30000 // 30秒缓存
);
}
// 多次调用相同用户ID,只会发起一次请求
Promise.all([
fetchUserData(1),
fetchUserData(1),
fetchUserData(1)
]).then(results => console.log(results));
📝 本章小结
本章深入探讨了JavaScript异步编程的高级技术:
- Promise原理:理解状态机制和链式调用的实现
- async/await:掌握其Generator + Promise的本质
- Generator应用:实现协程、异步迭代等高级模式
- 并发控制:限流、去重、缓存等实用技术
这些技术将帮助你:
- 编写更优雅的异步代码
- 处理复杂的并发场景
- 优化应用性能和用户体验
- 避免常见的异步编程陷阱
🚀 下一章预告
下一章我们将学习内存管理与性能优化,深入了解垃圾回收机制、内存泄漏检测和性能分析工具的使用。
继续学习:第3章:内存管理与性能优化