什么是 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); // 10
return asyncOperation2(result1);
})
.then(result2 => {
console.log('第二步结果:', result2); // 20
return 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 和现代前端开发至关重要。