面试题答案
一键面试性能优势
- 代码可读性与维护性提升:
- 传统回调函数:会出现回调地狱问题,例如多层嵌套的
setTimeout
回调:
这样的代码逻辑复杂,难以阅读和维护。setTimeout(() => { setTimeout(() => { setTimeout(() => { console.log('回调地狱'); }, 1000); }, 1000); }, 1000);
- Promise:通过链式调用解决了回调地狱问题,例如:
new Promise((resolve) => { setTimeout(() => { resolve(); }, 1000); })
- 传统回调函数:会出现回调地狱问题,例如多层嵌套的
.then(() => { return new Promise((resolve) => { setTimeout(() => { resolve(); }, 1000); }); }) .then(() => { console.log('Promise 链式调用'); });
但链式调用依然不够简洁。
- **async/await**:以同步风格编写异步代码,例如:
```javascript
async function asyncFunc() {
await new Promise((resolve) => {
setTimeout(() => {
resolve();
}, 1000);
});
await new Promise((resolve) => {
setTimeout(() => {
resolve();
}, 1000);
});
console.log('async/await 同步风格');
}
asyncFunc();
代码结构更清晰,减少人为错误,从间接提升性能(因代码易读易维护,可减少调试和优化时间)。 2. 错误处理简化:
- 传统回调函数:错误处理需要在每个回调函数中单独进行,例如:
function asyncTask(callback) {
setTimeout(() => {
const error = true;
if (error) {
callback(new Error('出错了'));
} else {
callback(null, '成功');
}
}, 1000);
}
asyncTask((err, result) => {
if (err) {
console.error(err);
} else {
console.log(result);
}
});
多个异步操作时,错误处理代码重复且繁琐。
- Promise:通过
.catch
统一处理错误,例如:
new Promise((resolve, reject) => {
setTimeout(() => {
const error = true;
if (error) {
reject(new Error('出错了'));
} else {
resolve('成功');
}
}, 1000);
})
.then((result) => {
console.log(result);
})
.catch((err) => {
console.error(err);
});
- async/await:使用
try...catch
块处理错误,更接近同步代码的错误处理方式,例如:
async function asyncTask() {
try {
await new Promise((resolve, reject) => {
setTimeout(() => {
const error = true;
if (error) {
reject(new Error('出错了'));
} else {
resolve('成功');
}
}, 1000);
});
} catch (err) {
console.error(err);
}
}
asyncTask();
简化的错误处理使代码更简洁,减少错误处理逻辑带来的性能开销(如重复代码执行等)。
适用场景
- 顺序执行异步操作:
- 例如在用户注册流程中,先检查用户名是否存在,再创建用户,最后发送欢迎邮件。
async function registerUser(username, password) { try { // 检查用户名是否存在 const exists = await checkUsernameExists(username); if (exists) { throw new Error('用户名已存在'); } // 创建用户 const user = await createUser(username, password); // 发送欢迎邮件 await sendWelcomeEmail(user.email); console.log('用户注册成功'); } catch (err) { console.error(err); } } async function checkUsernameExists(username) { return new Promise((resolve) => { setTimeout(() => { resolve(false); }, 1000); }); } async function createUser(username, password) { return new Promise((resolve) => { setTimeout(() => { resolve({ username, password, email: 'user@example.com' }); }, 1000); }); } async function sendWelcomeEmail(email) { return new Promise((resolve) => { setTimeout(() => { console.log(`已向 ${email} 发送欢迎邮件`); resolve(); }, 1000); }); } registerUser('testuser', 'testpassword');
- 处理多个异步操作结果后进行下一步:
- 例如在获取多个 API 数据后进行合并处理。假设要从两个 API 获取用户信息和订单信息,然后合并展示。
在这个场景中,async function getUserAndOrderInfo() { try { const userPromise = getUserInfo(); const orderPromise = getOrderInfo(); const [user, order] = await Promise.all([userPromise, orderPromise]); const combinedInfo = { user, order }; console.log(combinedInfo); } catch (err) { console.error(err); } } async function getUserInfo() { return new Promise((resolve) => { setTimeout(() => { resolve({ name: 'John', age: 30 }); }, 1000); }); } async function getOrderInfo() { return new Promise((resolve) => { setTimeout(() => { resolve({ orderId: 123, amount: 100 }); }, 1000); }); } getUserAndOrderInfo();
async/await
结合Promise.all
能清晰地处理多个异步操作,并在所有操作完成后进行统一处理。