Promise的玩法

一、Promise基础概念

1.1 核心特性

Promise是ES6引入的异步编程解决方案,具有三大核心特性:

  • 状态不可逆性:仅能从pending→fulfilled或pending→rejected单向转换
  • 链式调用:通过then/catch串联异步操作
  • 统一错误处理:catch集中捕获链式调用中的异常

1.2 基本结构

js 复制代码
const fetchData = new Promise((resolve, reject) => {  
// 异步操作  
setTimeout(() => {     
resolve('操作成功'); // 成功状态
// reject(new Error('操作失败')); // 失败状态  
}, 1000);
});
fetchData.then(data => console.log(data)) // 成功回调  
.catch(err => console.error(err)); // 错误处理 

二、进阶应用场景

2.1 异步流程控制

串行请求(依赖前序结果)

js 复制代码
function getUser(id) {   return fetch(`/api/users/${id}`).then(res => res.json()); }  
function getPosts(userId) {   return fetch(`/api/posts/${userId}`).then(res => res.json()); }  // 自动等待前序请求完成
getUser(1).then(user => getPosts(user.id)).then(posts => console.log(posts)).catch(console.error); 

并行请求(Promise.all)

js 复制代码
Promise.all([   fetch('/api/users').then(res => res.json()),  
fetch('/api/posts').then(res => res.json()) ]).then(([users, posts]) => {  
console.log('用户数据:', users);  
console.log('帖子数据:', posts); 
}); 

2.2 错误处理机制

穿透式错误捕获

js 复制代码
fetchData.then(processData).then(saveData).catch(err => {     
console.error('流程中断:', err);     
return Promise.reject(err); // 保持错误传递  
}); 

2.3 状态管理进阶

手动状态控制(模拟加载状态)

js 复制代码
class DataLoader {  
constructor() {    
this.promise = new Promise((resolve, reject) => {      
this.resolve = resolve;       
this.reject = reject;});  
}      
load() {    
// 模拟异步加载     
setTimeout(() => {      
this.resolve(loadedData);}, 1000);   
}    
cancel() {     
this.reject(new Error('操作取消'));  
} } 

三、企业级实践方案

3.1 请求封装示例

js 复制代码
class APIClient { 
constructor(baseURL) {     this.baseURL = baseURL;   }     
request(options) {    
return new Promise((resolve, reject) => {    
const xhr = new XMLHttpRequest();       
xhr.open(options.method, `${this.baseURL}${options.path}`);           
xhr.onload = () => {        
if (xhr.status >= 200 && xhr.status < 300) {         
resolve(JSON.parse(xhr.response));         
} else {          
reject(new Error(`请求失败: ${xhr.status}`));         
}       };              
xhr.onerror = () => reject(new Error('网络错误'));      
xhr.send(options.data || null);});   
} }  
// 使用示例 
const client = new APIClient('https://api.example.com');
client.request({   method: 'GET',   path: '/users' }) .then(users => console.log(users)) .catch(console.error); 

3.2 性能优化策略

请求池化技术

js 复制代码
class RequestPool {   
constructor(maxConcurrent = 5) {    
this.queue = [];    
this.running = 0;     
this.max = maxConcurrent;   
}     
add(promise) {    
this.queue.push(promise);    
if (this.running < this.max) {       
this._runNext();     
}     
return promise;   }     
_runNext() {     
if (this.queue.length === 0) return;          
const task = this.queue.shift();     
task.finally(() => {       
this.running--;        
this._runNext();      
});     
this.running++;   } }  
// 使用示例 
const pool = new RequestPool(3); 
for (let i = 0; i < 8; i++) {   
pool.add(fetch(`/api/data/${i}`)); 
} 

四、常见问题解析

4.1 执行顺序陷阱

js 复制代码
console.log(1); 
new Promise(resolve => {   
console.log(2);   
setTimeout(() => {    
console.log('timer');    
resolve();   }, 0);   
console.log(3); }) .then(() => console.log(4)); 
console.log(5); // 输出顺序: 1 → 2 → 3 → 5 → timer → 4 
相关推荐
渣波17 分钟前
拒绝黑盒!NestJS + LangChain 实战保姆级拆解,手把手教你搞定双 Token 与 AI 大脑
前端·后端
SL_staff17 分钟前
3周搭完MES系统:JVS低代码+JVS-IoT物联网的实战记录
java·前端·低代码
秋天的一阵风17 分钟前
Vue 3 里被严重低估的 API:InjectionKey
前端·javascript·vue.js
恋猫de小郭22 分钟前
Flutter Patchwork,不用 Fork 改依赖包源码的第三方工具
android·前端·flutter
IT_陈寒1 小时前
Vite打包后的路径问题差点让我改了一天代码
前端·人工智能·后端
禅思院1 小时前
前端部署“三层漏斗”完全指南:从CI/CD到自动回滚的工程化实战【基石】
前端·架构·前端框架
黄林晴1 小时前
AI时代终端窗口堆成山?这款工具让我爱不释手
前端
铁皮饭盒1 小时前
Bun 多线程有多快?postMessage 传输字符串比 Node.js 快 400 倍!
前端·javascript·后端
橙子家11 小时前
浏览器缓存之【身份与会话管理】:Cookies 和 Private state tokens
前端
最新资讯动态12 小时前
HDC 2026 | 对话鲸鸿动能:存量时代,品牌如何夺回营销“主动权”?
前端