JavaScript系列(18)--异步编程模式
JavaScript异步编程模式 🔄
今天,让我们深入探讨JavaScript中的异步编程模式。异步编程是JavaScript中非常重要的概念,它帮助我们处理非阻塞操作和提高应用性能。
异步编程基础 🌟
💡 小知识:JavaScript是单线程的,但通过事件循环和异步编程模式,我们可以实现非阻塞的操作,从而提高应用的响应性和性能。
回调函数模式 📊
// 1. 基本回调模式
function callbackPatterns() {
// 简单回调
function fetchData(callback) {
setTimeout(() => {
const data = { id: 1, name: 'Example' };
callback(null, data);
}, 1000);
}
// 错误优先回调
fetchData((error, data) => {
if (error) {
console.error('Error:', error);
return;
}
console.log('Data:', data);
});
// 嵌套回调(回调地狱)
fetchData((error1, data1) => {
if (error1) return console.error(error1);
fetchData((error2, data2) => {
if (error2) return console.error(error2);
fetchData((error3, data3) => {
if (error3) return console.error(error3);
console.log('All data:', data1, data2, data3);
});
});
});
}
// 2. 回调函数改进
class CallbackManager {
// 串行执行回调
static series(tasks, finalCallback) {
const results = [];
let completed = 0;
function next() {
if (completed >= tasks.length) {
finalCallback(null, results);
return;
}
tasks[completed]((error, result) => {
if (error) {
finalCallback(error);
return;
}
results.push(result);
completed++;
next();
});
}
next();
}
// 并行执行回调
static parallel(tasks, finalCallback) {
const results = new Array(tasks.length);
let completed = 0;
let hasError = false;
tasks.forEach((task, index) => {
task((error, result) => {
if (hasError) return;
if (error) {
hasError = true;
finalCallback(error);
return;
}
results[index] = result;
completed++;
if (completed === tasks.length) {
finalCallback(null, results);
}
});
});
}
}
// 3. 事件发射器模式
class EventEmitter {
constructor() {
this.events = new Map();
}
on(event, callback) {
if (!this.events.has(event)) {
this.events.set(event, []);
}
this.events.get(event).push(callback);
return () => this.off(event, callback);
}
off(event, callback) {
const callbacks = this.events.get(event);
if (callbacks) {
const index = callbacks.indexOf(callback);
if (index !== -1) {
callbacks.splice(index, 1);
}
}
}
emit(event, ...args) {
const callbacks = this.events.get(event);
if (callbacks) {
callbacks.forEach(callback => callback(...args));
}
}
once(event, callback) {
const wrapper = (...args) => {
callback(...args);
this.off(event, wrapper);
};
return this.on(event, wrapper);
}
}
Promise模式 🔄
// 1. Promise基础操作
class PromisePatterns {
// 创建Promise
static createPromise() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const random = Math.random();
if (random > 0.5) {
resolve('Success!');
} else {
reject(new Error('Failed!'));
}
}, 1000);
});
}
// Promise链式调用
static chainPromises() {
return this.createPromise()
.then(result => {
console.log('First then:', result);
return 'Next value';
})
.then(result => {
console.log('Second then:', result);
throw new Error('Custom error');
})
.catch(error => {
console.error('Caught error:', error);
return 'Recovered';
})
.finally(() => {
console.log('Finally block executed');
});
}
// Promise并行执行
static parallel() {
const promises = [
this.createPromise(),
this.createPromise(),
this.createPromise()
];
return Promise.all(promises)
.then(results => {
console.log('All succeeded:', results);
})
.catch(error => {
console.error('One failed:', error);
});
}
}
// 2. Promise工具函数
class PromiseUtils {
// 超时包装
static timeout(promise, ms) {
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error('Timeout')), ms);
});
return Promise.race([promise, timeoutPromise]);
}
// 重试机制
static retry(fn, retries = 3, delay = 1000) {
return new Promise((resolve, reject) => {
function attempt() {
fn().then(resolve).catch(error => {
if (retries === 0) {
reject(error);
return;
}
retries--;
setTimeout(attempt, delay);
});
}
attempt();
});
}
// 串行执行Promise
static series(tasks) {
return tasks.reduce(
(promise, task) => promise.then(results =>
task().then(result => [...results, result])
),
Promise.resolve([])
);
}
}
// 3. Promise池
class PromisePool {
constructor(maxConcurrent) {
this.maxConcurrent = maxConcurrent;
this.running = 0;
this.queue = [];
}
add(promiseFactory) {
return new Promise((resolve, reject) => {
this.queue.push({ promiseFactory, resolve, reject });
this.run();
});
}
run() {
while (this.running < this.maxConcurrent && this.queue.length > 0) {
const { promiseFactory, resolve, reject } = this.queue.shift();
this.running++;
promiseFactory()
.then(resolve)
.catch(reject)
.finally(() => {
this.running--;
this.run();
});
}
}
}
Async/Await模式 🔄
// 1. 基本使用
class AsyncAwaitPatterns {
// 异步函数
static async fetchData() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
return data;
} catch (error) {
console.error('Error fetching data:', error);
throw error;
}
}
// 并行执行
static async parallel() {
try {
const [result1, result2] = await Promise.all([
this.fetchData(),
this.fetchData()
]);
return { result1, result2 };
} catch (error) {
console.error('Error in parallel execution:', error);
throw error;
}
}
// 串行执行
static async series() {
try {
const result1 = await this.fetchData();
const result2 = await this.fetchData();
return { result1, result2 };
} catch (error) {
console.error('Error in series execution:', error);
throw error;
}
}
}
// 2. 异步迭代器
class AsyncIteratorPatterns {
// 异步生成器
static async *generateData() {
for (let i = 0; i < 5; i++) {
await new Promise(resolve => setTimeout(resolve, 1000));
yield i;
}
}
// 使用for-await-of
static async consumeData() {
for await (const value of this.generateData()) {
console.log('Generated value:', value);
}
}
// 自定义异步迭代器
static createAsyncIterator(array) {
let index = 0;
return {
async next() {
if (index < array.length) {
await new Promise(resolve => setTimeout(resolve, 1000));
return { value: array[index++], done: false };
}
return { done: true };
},
[Symbol.asyncIterator]() {
return this;
}
};
}
}
// 3. 异步工具函数
class AsyncUtils {
// 异步重试
static async retry(fn, options = {}) {
const {
retries = 3,
delay = 1000,
onRetry = null
} = options;
let lastError;
for (let i = 0; i < retries; i++) {
try {
return await fn();
} catch (error) {
lastError = error;
if (onRetry) {
onRetry(error, i + 1);
}
if (i < retries - 1) {
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
throw lastError;
}
// 异步超时
static async timeout(promise, ms) {
let timeoutId;
const timeoutPromise = new Promise((_, reject) => {
timeoutId = setTimeout(() => {
reject(new Error(`Operation timed out after ${ms}ms`));
}, ms);
});
try {
const result = await Promise.race([promise, timeoutPromise]);
clearTimeout(timeoutId);
return result;
} catch (error) {
clearTimeout(timeoutId);
throw error;
}
}
// 异步批处理
static async batch(items, batchSize, processor) {
const results = [];
for (let i = 0; i < items.length; i += batchSize) {
const batch = items.slice(i, i + batchSize);
const batchResults = await Promise.all(
batch.map(item => processor(item))
);
results.push(...batchResults);
}
return results;
}
}
性能优化 ⚡
异步编程中的性能优化技巧:
// 1. 并发控制
class ConcurrencyControl {
constructor(maxConcurrent = 5) {
this.maxConcurrent = maxConcurrent;
this.running = 0;
this.queue = [];
}
async add(task) {
if (this.running >= this.maxConcurrent) {
await new Promise(resolve => this.queue.push(resolve));
}
this.running++;
try {
return await task();
} finally {
this.running--;
if (this.queue.length > 0) {
const next = this.queue.shift();
next();
}
}
}
}
// 2. 缓存优化
class AsyncCache {
constructor() {
this.cache = new Map();
this.pending = new Map();
}
async get(key, fetcher) {
// 检查缓存
if (this.cache.has(key)) {
return this.cache.get(key);
}
// 检查是否有pending请求
if (this.pending.has(key)) {
return this.pending.get(key);
}
// 创建新请求
const promise = fetcher().then(result => {
this.cache.set(key, result);
this.pending.delete(key);
return result;
});
this.pending.set(key, promise);
return promise;
}
invalidate(key) {
this.cache.delete(key);
this.pending.delete(key);
}
}
// 3. 资源池化
class ResourcePool {
constructor(factory, options = {}) {
this.factory = factory;
this.resources = [];
this.maxSize = options.maxSize || 10;
this.minSize = options.minSize || 2;
this.createInitialResources();
}
async createInitialResources() {
for (let i = 0; i < this.minSize; i++) {
const resource = await this.factory();
this.resources.push(resource);
}
}
async acquire() {
if (this.resources.length > 0) {
return this.resources.pop();
}
if (this.resources.length < this.maxSize) {
return await this.factory();
}
return new Promise(resolve => {
this.waitQueue.push(resolve);
});
}
async release(resource) {
if (this.waitQueue.length > 0) {
const resolve = this.waitQueue.shift();
resolve(resource);
} else if (this.resources.length < this.maxSize) {
this.resources.push(resource);
}
}
}
最佳实践建议 💡
- 错误处理
// 1. 全局错误处理
class AsyncErrorHandler {
static handleAsyncErrors(fn) {
return async (...args) => {
try {
return await fn(...args);
} catch (error) {
console.error('Async error:', error);
this.reportError(error);
throw error;
}
};
}
static reportError(error) {
// 实现错误报告逻辑
}
}
// 2. 优雅降级
class GracefulDegradation {
static async withFallback(primaryFn, fallbackFn) {
try {
return await primaryFn();
} catch (error) {
console.warn('Primary function failed, using fallback:', error);
return fallbackFn();
}
}
}
// 3. 重试策略
class RetryStrategy {
static async withBackoff(fn, maxRetries = 3) {
let retryCount = 0;
while (true) {
try {
return await fn();
} catch (error) {
retryCount++;
if (retryCount >= maxRetries) {
throw error;
}
const delay = Math.pow(2, retryCount) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
}
结语 📝
异步编程是JavaScript中非常重要的概念,掌握各种异步模式可以帮助我们写出更高效、更可维护的代码。我们学习了:
- 回调函数模式及其改进
- Promise的使用和工具函数
- Async/Await的最佳实践
- 性能优化技巧
- 错误处理策略
💡 学习建议:从简单的回调开始,逐步掌握Promise和Async/Await。注意错误处理和性能优化,选择合适的模式来处理不同的异步场景。
如果你觉得这篇文章有帮助,欢迎点赞收藏,也期待在评论区看到你的想法和建议!👇
终身学习,共同成长。
咱们下一期见
💻