Search K
Appearance
Appearance
📊 SEO元描述:2024年最新JavaScript Promise高级应用教程,详解Promise链式调用原理、错误传播机制、并发控制实现。包含完整实战案例和性能优化策略,适合高级前端开发者深入掌握Promise。
核心关键词:JavaScript Promise高级应用2024、Promise链式调用原理、Promise错误传播、Promise并发控制、异步流程控制
长尾关键词:Promise链式调用怎么实现、Promise错误传播机制、Promise并发控制策略、JavaScript异步流程控制、Promise性能优化
通过本节JavaScript Promise高级应用详解,你将系统性掌握:
Promise链式调用是如何工作的?这是理解Promise高级应用的核心问题。Promise链式调用的原理基于每个then/catch/finally方法都返回新Promise的机制,通过值传递和状态传播实现复杂的异步流程控制。
💡 学习建议:理解Promise链式调用原理需要从Promise的内部实现机制出发,通过实际代码来观察状态传播和值传递的过程。
// 🎉 Promise链式调用内部机制详解
console.log("=== Promise链式调用内部机制详解 ===");
// 模拟Promise链的内部工作原理
class SimplePromiseChain {
constructor() {
this.handlers = [];
this.state = 'pending';
this.value = undefined;
}
// 模拟then方法
then(onFulfilled, onRejected) {
console.log("创建新的Promise链节点");
return new SimplePromiseChain().handle({
onFulfilled: onFulfilled || null,
onRejected: onRejected || null,
resolve: null,
reject: null
});
}
// 处理链式调用
handle(handler) {
if (this.state === 'pending') {
this.handlers.push(handler);
} else {
this.handleResolved(handler);
}
return this;
}
handleResolved(handler) {
setTimeout(() => {
const callback = this.state === 'fulfilled'
? handler.onFulfilled
: handler.onRejected;
if (!callback) {
const action = this.state === 'fulfilled'
? handler.resolve
: handler.reject;
action && action(this.value);
return;
}
try {
const result = callback(this.value);
handler.resolve && handler.resolve(result);
} catch (error) {
handler.reject && handler.reject(error);
}
}, 0);
}
resolve(value) {
this.state = 'fulfilled';
this.value = value;
this.handlers.forEach(handler => this.handleResolved(handler));
}
reject(reason) {
this.state = 'rejected';
this.value = reason;
this.handlers.forEach(handler => this.handleResolved(handler));
}
}
// Promise链式调用的值传递机制
function promiseChainValuePassing() {
console.log("1. Promise链式调用的值传递机制");
// 观察值在Promise链中的传递
Promise.resolve("初始值")
.then(value => {
console.log("第1步接收:", value);
console.log("第1步返回: 转换后的值");
return "转换后的值";
})
.then(value => {
console.log("第2步接收:", value);
console.log("第2步返回: Promise对象");
// 返回Promise对象
return new Promise(resolve => {
setTimeout(() => {
resolve("异步处理结果");
}, 1000);
});
})
.then(value => {
console.log("第3步接收:", value); // Promise被自动展平
console.log("第3步返回: undefined");
// 没有return语句,相当于return undefined
})
.then(value => {
console.log("第4步接收:", value); // undefined
console.log("第4步返回: 对象");
return { processed: true, data: "最终数据" };
})
.then(value => {
console.log("最终结果:", value);
});
}
// Promise链中的异步展平
function promiseChainFlattening() {
console.log("\n2. Promise链中的异步展平");
// 演示Promise的自动展平机制
function createNestedPromise(level, value) {
console.log(`创建第${level}层Promise`);
if (level <= 0) {
return Promise.resolve(value);
}
return new Promise(resolve => {
setTimeout(() => {
console.log(`第${level}层Promise resolve`);
resolve(createNestedPromise(level - 1, value));
}, 200);
});
}
Promise.resolve("开始")
.then(value => {
console.log("开始处理:", value);
return createNestedPromise(3, "嵌套Promise结果");
})
.then(value => {
console.log("自动展平后的结果:", value);
console.log("无论嵌套多少层,都会被自动展平");
});
}
// Promise链的分支和合并
function promiseChainBranchingMerging() {
console.log("\n3. Promise链的分支和合并");
const mainPromise = Promise.resolve("主流程数据");
// 从主Promise创建多个分支
const branch1 = mainPromise.then(data => {
console.log("分支1处理:", data);
return new Promise(resolve => {
setTimeout(() => resolve(`分支1结果: ${data}`), 800);
});
});
const branch2 = mainPromise.then(data => {
console.log("分支2处理:", data);
return new Promise(resolve => {
setTimeout(() => resolve(`分支2结果: ${data}`), 1200);
});
});
const branch3 = mainPromise.then(data => {
console.log("分支3处理:", data);
return new Promise(resolve => {
setTimeout(() => resolve(`分支3结果: ${data}`), 600);
});
});
// 合并所有分支的结果
Promise.all([branch1, branch2, branch3])
.then(results => {
console.log("所有分支完成:", results);
return results.join(" | ");
})
.then(mergedResult => {
console.log("合并后的结果:", mergedResult);
});
}
// 运行演示
promiseChainValuePassing();
promiseChainFlattening();
promiseChainBranchingMerging();// 🎉 Promise错误传播机制深入
console.log("=== Promise错误传播机制深入 ===");
// 错误传播的基本规则
function errorPropagationRules() {
console.log("1. 错误传播的基本规则");
Promise.resolve("正常开始")
.then(value => {
console.log("步骤1:", value);
return "步骤1完成";
})
.then(value => {
console.log("步骤2:", value);
throw new Error("步骤2发生错误");
})
.then(value => {
console.log("步骤3: 不会执行,因为前面有错误");
return "步骤3完成";
})
.then(value => {
console.log("步骤4: 也不会执行");
return "步骤4完成";
})
.catch(error => {
console.log("错误被捕获:", error.message);
console.log("错误处理完成,返回恢复值");
return "错误已恢复";
})
.then(value => {
console.log("恢复后继续:", value);
return "最终完成";
})
.then(value => {
console.log("最终结果:", value);
});
}
// 复杂的错误处理策略
function complexErrorHandling() {
console.log("\n2. 复杂的错误处理策略");
// 创建错误处理器
class PromiseErrorHandler {
constructor() {
this.errorLog = [];
this.retryCount = new Map();
}
// 带重试的错误处理
withRetry(promiseFactory, maxRetries = 3, retryDelay = 1000) {
const attemptKey = promiseFactory.toString();
let attempts = this.retryCount.get(attemptKey) || 0;
const attempt = () => {
attempts++;
this.retryCount.set(attemptKey, attempts);
console.log(`尝试第 ${attempts} 次...`);
return promiseFactory()
.catch(error => {
this.logError(error, attempts);
if (attempts < maxRetries && this.shouldRetry(error)) {
console.log(`${retryDelay}ms 后重试...`);
return new Promise(resolve => {
setTimeout(() => {
resolve(attempt());
}, retryDelay);
});
} else {
console.log(`重试失败,已达到最大重试次数 ${maxRetries}`);
throw new Error(`操作失败,已重试 ${attempts} 次: ${error.message}`);
}
});
};
return attempt();
}
// 错误分类处理
categorizeError(error) {
if (error.message.includes('网络')) {
return 'NETWORK_ERROR';
} else if (error.message.includes('超时')) {
return 'TIMEOUT_ERROR';
} else if (error.message.includes('权限')) {
return 'PERMISSION_ERROR';
} else {
return 'UNKNOWN_ERROR';
}
}
// 判断是否应该重试
shouldRetry(error) {
const category = this.categorizeError(error);
return ['NETWORK_ERROR', 'TIMEOUT_ERROR'].includes(category);
}
// 记录错误
logError(error, attempt) {
this.errorLog.push({
error: error.message,
category: this.categorizeError(error),
attempt,
timestamp: new Date().toISOString()
});
}
// 获取错误统计
getErrorStats() {
return this.errorLog;
}
}
const errorHandler = new PromiseErrorHandler();
// 模拟不稳定的网络请求
function unstableNetworkRequest() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const rand = Math.random();
if (rand < 0.3) {
resolve("请求成功");
} else if (rand < 0.6) {
reject(new Error("网络连接失败"));
} else if (rand < 0.8) {
reject(new Error("请求超时"));
} else {
reject(new Error("权限不足"));
}
}, 500);
});
}
// 使用错误处理器
errorHandler.withRetry(() => unstableNetworkRequest(), 5, 800)
.then(result => {
console.log("最终成功:", result);
console.log("错误统计:", errorHandler.getErrorStats());
})
.catch(error => {
console.log("最终失败:", error.message);
console.log("错误统计:", errorHandler.getErrorStats());
});
}
// 错误恢复和降级策略
function errorRecoveryStrategies() {
console.log("\n3. 错误恢复和降级策略");
// 多级降级策略
function fetchDataWithFallback(primaryUrl, backupUrl, cacheKey) {
console.log("开始多级数据获取策略...");
// 尝试主数据源
return fetchFromPrimary(primaryUrl)
.catch(primaryError => {
console.log("主数据源失败:", primaryError.message);
console.log("尝试备用数据源...");
// 尝试备用数据源
return fetchFromBackup(backupUrl)
.catch(backupError => {
console.log("备用数据源失败:", backupError.message);
console.log("尝试缓存数据...");
// 尝试缓存数据
return fetchFromCache(cacheKey)
.catch(cacheError => {
console.log("缓存数据失败:", cacheError.message);
console.log("使用默认数据...");
// 最后使用默认数据
return {
data: "默认数据",
source: "default",
warning: "所有数据源都不可用,使用默认数据"
};
});
});
});
}
// 模拟各种数据源
function fetchFromPrimary(url) {
return new Promise((resolve, reject) => {
setTimeout(() => {
Math.random() < 0.3
? resolve({ data: "主数据源数据", source: "primary" })
: reject(new Error("主数据源不可用"));
}, 800);
});
}
function fetchFromBackup(url) {
return new Promise((resolve, reject) => {
setTimeout(() => {
Math.random() < 0.5
? resolve({ data: "备用数据源数据", source: "backup" })
: reject(new Error("备用数据源不可用"));
}, 1200);
});
}
function fetchFromCache(key) {
return new Promise((resolve, reject) => {
setTimeout(() => {
Math.random() < 0.7
? resolve({ data: "缓存数据", source: "cache" })
: reject(new Error("缓存数据过期"));
}, 200);
});
}
fetchDataWithFallback("/api/data", "/api/backup", "data_cache")
.then(result => {
console.log("最终获取到数据:", result);
if (result.warning) {
console.warn("警告:", result.warning);
}
});
}
// 运行演示
errorPropagationRules();
complexErrorHandling();
errorRecoveryStrategies();// 🎉 Promise并发数量控制
console.log("=== Promise并发数量控制 ===");
// 实现并发控制器
class ConcurrencyController {
constructor(maxConcurrency = 3) {
this.maxConcurrency = maxConcurrency;
this.running = 0;
this.queue = [];
}
// 添加任务到队列
add(promiseFactory) {
return new Promise((resolve, reject) => {
this.queue.push({
promiseFactory,
resolve,
reject
});
this.process();
});
}
// 处理队列中的任务
async process() {
if (this.running >= this.maxConcurrency || this.queue.length === 0) {
return;
}
this.running++;
const { promiseFactory, resolve, reject } = this.queue.shift();
try {
console.log(`开始执行任务,当前并发数: ${this.running}`);
const result = await promiseFactory();
resolve(result);
} catch (error) {
reject(error);
} finally {
this.running--;
console.log(`任务完成,当前并发数: ${this.running}`);
this.process(); // 处理下一个任务
}
}
// 批量处理任务
async processAll(promiseFactories) {
const promises = promiseFactories.map(factory => this.add(factory));
return Promise.all(promises);
}
// 获取状态
getStatus() {
return {
running: this.running,
queued: this.queue.length,
maxConcurrency: this.maxConcurrency
};
}
}
// 使用并发控制器
function demonstrateConcurrencyControl() {
console.log("1. 并发控制器演示");
const controller = new ConcurrencyController(2); // 最大并发数为2
// 创建多个异步任务
const tasks = Array.from({ length: 8 }, (_, index) => {
return () => new Promise(resolve => {
const duration = Math.random() * 2000 + 1000;
console.log(`任务${index + 1}开始,预计耗时${Math.round(duration)}ms`);
setTimeout(() => {
console.log(`任务${index + 1}完成`);
resolve(`任务${index + 1}的结果`);
}, duration);
});
});
console.log("开始批量处理任务...");
const startTime = Date.now();
controller.processAll(tasks)
.then(results => {
const endTime = Date.now();
console.log("所有任务完成,耗时:", endTime - startTime, "ms");
console.log("结果:", results);
})
.catch(error => {
console.error("批量处理失败:", error);
});
// 定期显示状态
const statusInterval = setInterval(() => {
const status = controller.getStatus();
console.log("状态:", status);
if (status.running === 0 && status.queued === 0) {
clearInterval(statusInterval);
}
}, 500);
}
// 高级并发控制:带优先级的任务队列
class PriorityQueue {
constructor() {
this.items = [];
}
enqueue(item, priority = 0) {
const queueElement = { item, priority };
let added = false;
for (let i = 0; i < this.items.length; i++) {
if (queueElement.priority > this.items[i].priority) {
this.items.splice(i, 0, queueElement);
added = true;
break;
}
}
if (!added) {
this.items.push(queueElement);
}
}
dequeue() {
return this.items.shift()?.item;
}
isEmpty() {
return this.items.length === 0;
}
size() {
return this.items.length;
}
}
class AdvancedConcurrencyController {
constructor(maxConcurrency = 3) {
this.maxConcurrency = maxConcurrency;
this.running = 0;
this.queue = new PriorityQueue();
this.stats = {
completed: 0,
failed: 0,
totalTime: 0
};
}
// 添加带优先级的任务
add(promiseFactory, priority = 0, metadata = {}) {
return new Promise((resolve, reject) => {
this.queue.enqueue({
promiseFactory,
resolve,
reject,
priority,
metadata,
addedAt: Date.now()
}, priority);
this.process();
});
}
async process() {
if (this.running >= this.maxConcurrency || this.queue.isEmpty()) {
return;
}
this.running++;
const task = this.queue.dequeue();
const startTime = Date.now();
try {
console.log(`执行${task.metadata.name || '任务'},优先级: ${task.priority}`);
const result = await task.promiseFactory();
const duration = Date.now() - startTime;
this.stats.completed++;
this.stats.totalTime += duration;
console.log(`${task.metadata.name || '任务'}完成,耗时: ${duration}ms`);
task.resolve(result);
} catch (error) {
this.stats.failed++;
console.error(`${task.metadata.name || '任务'}失败:`, error.message);
task.reject(error);
} finally {
this.running--;
this.process();
}
}
getStats() {
return {
...this.stats,
averageTime: this.stats.completed > 0
? Math.round(this.stats.totalTime / this.stats.completed)
: 0,
running: this.running,
queued: this.queue.size()
};
}
}
// 使用高级并发控制器
function demonstrateAdvancedConcurrencyControl() {
console.log("\n2. 高级并发控制器演示");
const controller = new AdvancedConcurrencyController(2);
// 添加不同优先级的任务
const tasks = [
{ name: "低优先级任务1", priority: 1, duration: 2000 },
{ name: "高优先级任务1", priority: 10, duration: 1000 },
{ name: "低优先级任务2", priority: 1, duration: 1500 },
{ name: "中优先级任务1", priority: 5, duration: 1200 },
{ name: "高优先级任务2", priority: 10, duration: 800 },
{ name: "中优先级任务2", priority: 5, duration: 1800 }
];
console.log("添加任务到队列...");
const promises = tasks.map(task => {
return controller.add(
() => new Promise(resolve => {
setTimeout(() => resolve(`${task.name}完成`), task.duration);
}),
task.priority,
{ name: task.name }
);
});
Promise.all(promises)
.then(results => {
console.log("所有任务完成:", results);
console.log("执行统计:", controller.getStats());
});
}
// 运行演示
demonstrateConcurrencyControl();
demonstrateAdvancedConcurrencyControl();// 🎉 Promise流量控制和限流
console.log("=== Promise流量控制和限流 ===");
// 实现令牌桶限流器
class TokenBucketLimiter {
constructor(capacity = 10, refillRate = 1, refillInterval = 1000) {
this.capacity = capacity;
this.tokens = capacity;
this.refillRate = refillRate;
this.refillInterval = refillInterval;
this.queue = [];
// 定期补充令牌
this.refillTimer = setInterval(() => {
this.refill();
}, refillInterval);
}
// 补充令牌
refill() {
this.tokens = Math.min(this.capacity, this.tokens + this.refillRate);
console.log(`令牌补充,当前令牌数: ${this.tokens}`);
this.processQueue();
}
// 获取令牌执行任务
acquire(promiseFactory) {
return new Promise((resolve, reject) => {
if (this.tokens > 0) {
this.tokens--;
console.log(`获取令牌,剩余令牌: ${this.tokens}`);
this.executeTask(promiseFactory, resolve, reject);
} else {
console.log("令牌不足,加入等待队列");
this.queue.push({ promiseFactory, resolve, reject });
}
});
}
// 处理等待队列
processQueue() {
while (this.tokens > 0 && this.queue.length > 0) {
this.tokens--;
const { promiseFactory, resolve, reject } = this.queue.shift();
console.log(`从队列获取令牌,剩余令牌: ${this.tokens}`);
this.executeTask(promiseFactory, resolve, reject);
}
}
// 执行任务
async executeTask(promiseFactory, resolve, reject) {
try {
const result = await promiseFactory();
resolve(result);
} catch (error) {
reject(error);
}
}
// 获取状态
getStatus() {
return {
tokens: this.tokens,
capacity: this.capacity,
queueLength: this.queue.length
};
}
// 销毁限流器
destroy() {
clearInterval(this.refillTimer);
}
}
// 使用令牌桶限流器
function demonstrateTokenBucketLimiter() {
console.log("1. 令牌桶限流器演示");
const limiter = new TokenBucketLimiter(3, 1, 2000); // 容量3,每2秒补充1个令牌
// 创建多个请求
const requests = Array.from({ length: 8 }, (_, index) => {
return () => new Promise(resolve => {
console.log(`执行请求${index + 1}`);
setTimeout(() => {
resolve(`请求${index + 1}完成`);
}, 1000);
});
});
// 快速发起多个请求
console.log("快速发起8个请求...");
const promises = requests.map((request, index) => {
return limiter.acquire(request)
.then(result => {
console.log(`✅ ${result}`);
return result;
})
.catch(error => {
console.error(`❌ 请求${index + 1}失败:`, error.message);
});
});
Promise.all(promises)
.then(results => {
console.log("所有请求完成");
limiter.destroy();
});
// 定期显示状态
const statusInterval = setInterval(() => {
console.log("限流器状态:", limiter.getStatus());
}, 1000);
setTimeout(() => {
clearInterval(statusInterval);
}, 15000);
}
// 实现滑动窗口限流器
class SlidingWindowLimiter {
constructor(windowSize = 60000, maxRequests = 10) {
this.windowSize = windowSize;
this.maxRequests = maxRequests;
this.requests = [];
}
// 检查是否可以执行请求
canExecute() {
const now = Date.now();
// 清理过期的请求记录
this.requests = this.requests.filter(
timestamp => now - timestamp < this.windowSize
);
return this.requests.length < this.maxRequests;
}
// 执行请求
async execute(promiseFactory) {
if (!this.canExecute()) {
const oldestRequest = Math.min(...this.requests);
const waitTime = this.windowSize - (Date.now() - oldestRequest);
console.log(`请求频率过高,需要等待 ${waitTime}ms`);
await new Promise(resolve => setTimeout(resolve, waitTime));
if (!this.canExecute()) {
throw new Error("请求频率限制");
}
}
this.requests.push(Date.now());
console.log(`执行请求,窗口内请求数: ${this.requests.length}/${this.maxRequests}`);
return promiseFactory();
}
getStatus() {
const now = Date.now();
const activeRequests = this.requests.filter(
timestamp => now - timestamp < this.windowSize
);
return {
activeRequests: activeRequests.length,
maxRequests: this.maxRequests,
windowSize: this.windowSize
};
}
}
// 使用滑动窗口限流器
function demonstrateSlidingWindowLimiter() {
console.log("\n2. 滑动窗口限流器演示");
const limiter = new SlidingWindowLimiter(5000, 3); // 5秒窗口,最多3个请求
// 模拟API请求
function apiRequest(id) {
return new Promise(resolve => {
setTimeout(() => {
resolve(`API请求${id}响应`);
}, 500);
});
}
// 连续发起多个请求
async function makeRequests() {
for (let i = 1; i <= 6; i++) {
try {
console.log(`发起请求${i}...`);
const result = await limiter.execute(() => apiRequest(i));
console.log(`✅ ${result}`);
console.log("状态:", limiter.getStatus());
} catch (error) {
console.error(`❌ 请求${i}失败:`, error.message);
}
// 短暂延迟
await new Promise(resolve => setTimeout(resolve, 800));
}
}
makeRequests();
}
// 运行演示
demonstrateTokenBucketLimiter();
demonstrateSlidingWindowLimiter();通过本节JavaScript Promise高级应用详解的学习,你已经掌握:
A: Promise链式调用的性能很好,每个then都会创建新Promise,但这是轻量级操作。主要性能考虑在于避免过长的链和合理控制并发。
A: 可以在每个then中添加日志,使用浏览器的异步调试功能,或者使用async/await语法来简化调试过程。
A: 合理的并发控制能提高性能,避免资源过载。关键是根据系统资源和业务需求设置合适的并发数量。
A: 令牌桶适合突发流量,滑动窗口适合平滑限流。选择取决于具体的业务场景和流量特征。
A: 避免创建循环引用,及时清理不需要的Promise引用,合理使用WeakMap等弱引用数据结构。
"掌握Promise高级应用是成为JavaScript异步编程专家的关键技能。通过本节的学习,你已经具备了处理复杂异步场景的能力。接下来学习手写Promise实现,你将从底层理解Promise的工作原理,进一步提升异步编程的深度!"