Appearance
Promise 面试题
1. Promise 的基本概念
问题:什么是 Promise?它解决了什么问题?
答案: Promise 是异步编程的一种解决方案,用于表示一个异步操作的最终完成(或失败)及其结果值。
解决的问题:
- 回调地狱(Callback Hell)
- 异步代码的可读性和可维护性
- 错误处理的统一方式
- 多个异步操作的并发执行
Promise 的三种状态:
- pending:初始状态,既未完成也未拒绝
- fulfilled:操作成功完成
- rejected:操作失败
2. Promise 的基本用法
问题:如何创建和使用 Promise?
答案:
创建 Promise:
javascript
const promise = new Promise((resolve, reject) => {
// 异步操作
setTimeout(() => {
const success = true;
if (success) {
resolve('操作成功');
} else {
reject(new Error('操作失败'));
}
}, 1000);
});使用 Promise:
javascript
promise
.then(result => {
console.log(result); // '操作成功'
})
.catch(error => {
console.error(error.message);
})
.finally(() => {
console.log('操作完成');
});3. Promise 的链式调用
问题:Promise 的链式调用是如何工作的?
答案:
链式调用原理:
then()和catch()返回一个新的 Promise- 可以连续调用
then()形成链式操作 - 每个
then()接收上一个 Promise 的结果
示例:
javascript
fetchUser(1)
.then(user => {
console.log('用户:', user);
return fetchOrders(user.id); // 返回新的 Promise
})
.then(orders => {
console.log('订单:', orders);
return fetchProducts(orders[0].id);
})
.then(product => {
console.log('产品:', product);
})
.catch(error => {
console.error('错误:', error);
});返回值规则:
javascript
Promise.resolve(1)
.then(value => {
console.log(value); // 1
return value * 2; // 返回普通值
})
.then(value => {
console.log(value); // 2
return Promise.resolve(value * 2); // 返回 Promise
})
.then(value => {
console.log(value); // 4
// 不返回任何值
})
.then(value => {
console.log(value); // undefined
});4. Promise 的静态方法
问题:Promise 有哪些静态方法?它们的作用是什么?
答案:
Promise.resolve()
javascript
// 将值转换为 resolved 的 Promise
Promise.resolve('success');
Promise.resolve(Promise.resolve('value'));Promise.reject()
javascript
// 创建 rejected 的 Promise
Promise.reject(new Error('失败'));Promise.all()
javascript
// 等待所有 Promise 完成
const promises = [
fetchUser(1),
fetchUser(2),
fetchUser(3)
];
Promise.all(promises)
.then(users => {
console.log('所有用户:', users);
})
.catch(error => {
console.error('任一失败:', error);
});Promise.race()
javascript
// 返回最快完成的 Promise
const promises = [
fetchFromCache(),
fetchFromServer()
];
Promise.race(promises)
.then(result => {
console.log('最快的结果:', result);
});Promise.allSettled()
javascript
// 等待所有 Promise 完成,无论成功或失败
Promise.allSettled([
Promise.resolve('success'),
Promise.reject('error'),
Promise.resolve('another success')
])
.then(results => {
console.log(results);
// [
// { status: 'fulfilled', value: 'success' },
// { status: 'rejected', reason: 'error' },
// { status: 'fulfilled', value: 'another success' }
// ]
});Promise.any()
javascript
// 返回第一个成功的 Promise
Promise.any([
Promise.reject('error 1'),
Promise.resolve('success'),
Promise.reject('error 2')
])
.then(result => {
console.log('第一个成功:', result); // 'success'
})
.catch(error => {
// 所有都失败时
console.log(error.errors); // ['error 1', 'error 2']
});5. Promise 的错误处理
问题:Promise 中如何处理错误?
答案:
错误处理方式:
- catch() 方法:
javascript
fetchData()
.then(data => processData(data))
.catch(error => {
console.error('处理错误:', error);
});- then() 的第二个参数:
javascript
fetchData()
.then(
data => console.log(data),
error => console.error(error)
);- 全局错误处理:
javascript
process.on('unhandledRejection', (reason, promise) => {
console.error('未处理的 Promise 拒绝:', reason);
});错误传播:
javascript
Promise.resolve()
.then(() => {
throw new Error('第一步错误');
})
.then(() => {
// 不会执行
})
.catch(error => {
console.log(error.message); // '第一步错误'
throw new Error('catch 中的错误');
})
.catch(error => {
console.log(error.message); // 'catch 中的错误'
});6. async/await 与 Promise
问题:async/await 和 Promise 有什么关系?
答案:
关系:
- async/await 是 Promise 的语法糖
- async 函数返回 Promise
- await 等待 Promise 完成
对比:
javascript
// Promise 写法
function fetchUserData(userId) {
return fetchUser(userId)
.then(user => fetchOrders(user.id))
.then(orders => ({ user, orders }));
}
// async/await 写法
async function fetchUserData(userId) {
const user = await fetchUser(userId);
const orders = await fetchOrders(user.id);
return { user, orders };
}错误处理对比:
javascript
// Promise
fetchData()
.then(data => console.log(data))
.catch(error => console.error(error));
// async/await
try {
const data = await fetchData();
console.log(data);
} catch (error) {
console.error(error);
}7. Promise 的执行顺序
问题:以下代码的输出顺序是什么?
javascript
console.log('1');
setTimeout(() => console.log('2'), 0);
Promise.resolve().then(() => console.log('3'));
console.log('4');答案: 输出顺序:1 → 4 → 3 → 2
原因:
- 同步代码首先执行:1、4
- 微任务(Promise)在同步代码后执行:3
- 宏任务(setTimeout)最后执行:2
执行顺序规则:
- 同步代码
- 微任务(Promise、process.nextTick)
- 宏任务(setTimeout、setInterval、I/O)
8. Promise 的并发控制
问题:如何控制 Promise 的并发执行?
答案:
限制并发数:
javascript
async function asyncPool(poolLimit, array, iteratorFn) {
const ret = [];
const executing = [];
for (const item of array) {
const p = Promise.resolve().then(() => iteratorFn(item));
ret.push(p);
if (poolLimit <= array.length) {
const e = p.then(() => executing.splice(executing.indexOf(e), 1));
executing.push(e);
if (executing.length >= poolLimit) {
await Promise.race(executing);
}
}
}
return Promise.all(ret);
}
// 使用
const urls = ['url1', 'url2', 'url3', 'url4', 'url5'];
asyncPool(2, urls, fetchData);顺序执行:
javascript
async function runSequentially(tasks) {
const results = [];
for (const task of tasks) {
const result = await task();
results.push(result);
}
return results;
}9. Promise 的取消
问题:如何取消一个 Promise?
答案:
Promise 标准不支持取消,但可以通过包装实现:
javascript
function makeCancelable(promise) {
let isCanceled = false;
const wrappedPromise = new Promise((resolve, reject) => {
promise.then(
value => isCanceled ? reject({ isCanceled: true }) : resolve(value),
error => isCanceled ? reject({ isCanceled: true }) : reject(error)
);
});
return {
promise: wrappedPromise,
cancel() {
isCanceled = true;
}
};
}
// 使用
const { promise, cancel } = makeCancelable(fetchData());
promise
.then(data => console.log(data))
.catch(error => {
if (error.isCanceled) {
console.log('Promise 被取消');
}
});
// 取消
cancel();10. Promise 的最佳实践
问题:使用 Promise 有哪些最佳实践?
答案:
- 始终返回 Promise:
javascript
// 好
function getData() {
return fetchData().then(data => process(data));
}
// 不好
function getData() {
fetchData().then(data => process(data)); // 没有返回
}- 使用 catch 处理错误:
javascript
fetchData()
.then(data => process(data))
.catch(error => handleError(error));- 避免嵌套 Promise:
javascript
// 不好
fetchData().then(data => {
return fetchMoreData(data).then(moreData => {
return process(moreData);
});
});
// 好
fetchData()
.then(data => fetchMoreData(data))
.then(moreData => process(moreData));- 使用 Promise.all 并行执行:
javascript
// 顺序执行(慢)
const user = await fetchUser();
const orders = await fetchOrders();
// 并行执行(快)
const [user, orders] = await Promise.all([
fetchUser(),
fetchOrders()
]);- 使用 async/await 提高可读性:
javascript
async function getUserData(userId) {
try {
const user = await fetchUser(userId);
const orders = await fetchOrders(user.id);
return { user, orders };
} catch (error) {
console.error('获取用户数据失败:', error);
throw error;
}
}