Promise 详解
什么是 Promise?
Promise 是 JavaScript 中用于处理异步操作的对象,它代表一个异步操作的最终完成(或失败)及其结果值。
Promise 的三种状态
Promise 有三种状态,且状态一旦改变就不可逆转:
pending(等待中):初始状态,既不是成功,也不是失败
fulfilled(已成功):操作成功完成
rejected(已失败):操作失败
基本语法
const promise = new Promise((resolve, reject) => {// 异步操作if (/* 操作成功 */) {resolve(value); // 将状态改为 fulfilled} else {reject(error); // 将状态改为 rejected}
});Promise 的实例方法
1. .then()- 处理成功状态
promise.then((value) => {// 成功时的处理console.log('成功:', value);},(error) => {// 失败时的处理(可选)console.log('失败:', error);}
);2. .catch()- 处理失败状态
promise.catch((error) => {console.log('捕获错误:', error);
});3. .finally()- 无论成功失败都会执行
promise.finally(() => {console.log('无论成功失败都会执行');
});实际应用示例
示例 1:模拟异步操作
function fetchData() {return new Promise((resolve, reject) => {setTimeout(() => {const success = Math.random() > 0.3;if (success) {resolve('数据获取成功!');} else {reject('数据获取失败!');}}, 1000);});
}// 使用 Promise
fetchData().then(data => console.log(data)).catch(error => console.error(error)).finally(() => console.log('请求完成'));示例 2:模拟 AJAX 请求
function ajaxRequest(url) {return new Promise((resolve, reject) => {const xhr = new XMLHttpRequest();xhr.open('GET', url);xhr.onload = () => {if (xhr.status === 200) {resolve(JSON.parse(xhr.responseText));} else {reject(new Error(`请求失败: ${xhr.status}`));}};xhr.onerror = () => reject(new Error('网络错误'));xhr.send();});
}// 使用示例
ajaxRequest('https://api.example.com/data').then(data => console.log(data)).catch(error => console.error(error));Promise 的静态方法
1. Promise.all()- 所有 Promise 都成功
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve) => {setTimeout(resolve, 100, 'foo');
});Promise.all([promise1, promise2, promise3]).then(values => {console.log(values); // [3, 42, "foo"]}).catch(error => {// 如果任何一个 Promise 被拒绝,立即拒绝console.error(error);});2. Promise.race()- 第一个完成的 Promise
const promise1 = new Promise((resolve) => {setTimeout(resolve, 500, '第一个');
});const promise2 = new Promise((resolve) => {setTimeout(resolve, 100, '第二个');
});Promise.race([promise1, promise2]).then(value => {console.log(value); // "第二个"});3. Promise.allSettled()- 所有 Promise 都完成(无论成功失败)
const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, '失败')
);Promise.allSettled([promise1, promise2]).then(results => {results.forEach(result => console.log(result.status));// "fulfilled", "rejected"});4. Promise.any()- 第一个成功的 Promise
const promise1 = Promise.reject(0);
const promise2 = new Promise((resolve) => setTimeout(resolve, 100, '快的')
);
const promise3 = new Promise((resolve) => setTimeout(resolve, 500, '慢的')
);Promise.any([promise1, promise2, promise3]).then(value => {console.log(value); // "快的"});Promise 链式调用
function asyncOperation1() {return new Promise(resolve => {setTimeout(() => resolve(10), 1000);});
}function asyncOperation2(value) {return new Promise(resolve => {setTimeout(() => resolve(value * 2), 1000);});
}function asyncOperation3(value) {return new Promise(resolve => {setTimeout(() => resolve(value + 5), 1000);});
}// 链式调用
asyncOperation1().then(result1 => {console.log('第一步结果:', result1); // 10return asyncOperation2(result1);}).then(result2 => {console.log('第二步结果:', result2); // 20return asyncOperation3(result2);}).then(result3 => {console.log('最终结果:', result3); // 25}).catch(error => {console.error('错误:', error);});错误处理的最佳实践
// 好的错误处理方式
fetchData().then(data => {// 处理数据return processData(data);}).then(processedData => {// 使用处理后的数据console.log(processedData);}).catch(error => {// 统一处理所有错误console.error('操作失败:', error);});// 避免这种写法(反模式)
fetchData().then(data => {// 处理数据}, error => {// 这里的 catch 无法捕获 then 回调中的错误console.error(error);});async/await 与 Promise
async/await 是 Promise 的语法糖,让异步代码看起来像同步代码:
// 使用 Promise
function fetchUserData() {return fetch('/api/user').then(response => response.json()).then(data => console.log(data)).catch(error => console.error(error));
}// 使用 async/await
async function fetchUserData() {try {const response = await fetch('/api/user');const data = await response.json();console.log(data);} catch (error) {console.error(error);}
}常见面试题
1. Promise 的执行顺序
console.log('1');setTimeout(() => console.log('2'), 0);Promise.resolve().then(() => console.log('3'));console.log('4');// 输出顺序: 1, 4, 3, 2
// 解释:同步代码 > 微任务(Promise) > 宏任务(setTimeout)2. Promise 链式调用中的错误处理
Promise.resolve().then(() => {throw new Error('错误1');}).then(() => {console.log('这里不会执行');}).catch(error => {console.log('捕获错误:', error.message); // "错误1"throw new Error('错误2');}).catch(error => {console.log('再次捕获:', error.message); // "错误2"});总结
Promise 的主要优势:
避免回调地狱:使异步代码更易读和维护
更好的错误处理:统一的错误处理机制
链式调用:支持多个异步操作的顺序执行
并行处理:通过
Promise.all()等方法实现并行操作
Promise 是现代 JavaScript 异步编程的基础,理解 Promise 对于掌握 async/await 和现代前端开发至关重要。
