揭秘前端高薪岗:JS 异步编程(Promise/async/await)必考题汇总
在前端开发领域,JavaScript 异步编程是核心技能之一,而其中的 Promise、async/await 更是重中之重,在高薪岗位的面试中频繁出现。今天,我们就来深度汇总 JS 异步编程(Promise/async/await)的必考题,助力大家冲击前端高薪岗。
在前端开发领域,JavaScript 异步编程是核心技能之一,而其中的 Promise、async/await 更是重中之重,在高薪岗位的面试中频繁出现。今天,我们就来深度汇总 JS 异步编程(Promise/async/await)的必考题,助力大家冲击前端高薪岗。
Promise 基础必考题
- Promise 构造函数与 then 方法执行顺序
javascript
console.log('start');
const promise1 = new Promise((resolve, reject) => {
console.log(1);
resolve(2);
console.log(3);
});
promise1.then(res => {
console.log(res);
});
console.log('end');
解析:Promise 构造函数内的代码是同步执行的,所以先打印 start,接着执行 Promise 构造函数,打印 1 和 3,resolve(2) 会将 Promise 状态变为 fulfilled,并将 2 作为参数传递给 then 方法的回调函数。由于 then 方法的回调函数是异步执行的,所以先打印 end,最后打印 2。最终输出顺序为 start、1、3、end、2。
2. Promise 状态的不可逆性
javascript
const promise = new Promise((resolve, reject) => {
resolve('success1');
reject('error');
resolve('success2');
});
promise.then((res) => {
console.log('then:', res);
}).catch((err) => {
console.log('catch:', err);
});
解析:Promise 的状态一旦确定就不能再改变,这里 resolve('success1') 执行后,Promise 状态变为 fulfilled,后续的 reject('error') 和 resolve('success2') 都不会生效。所以最终打印 then: success1。
3. Promise 链式调用
javascript
Promise.resolve(1)
.then((res) => {
console.log(res);
return 2;
})
.catch((err) => {
return 3;
})
.then((res) => {
console.log(res);
});
解析:Promise 每次调用 then 或者 catch 都会返回一个新的 Promise,从而实现链式调用。Promise.resolve(1) 返回一个已解决的 Promise,值为 1,第一个 then 方法打印 1,并返回 2,这个 2 会被包装成一个已解决的 Promise 传递给下一个 then 方法,所以第二个 then 方法打印 2。由于第一个 then 方法没有抛出错误,所以 catch 方法不会执行。最终输出 1 和 2。
Promise 进阶必考题
- Promise 与 setTimeout 结合
javascript
console.log('start');
setTimeout(() => {
console.log('setTimeout');
}, 0);
Promise.resolve().then(() => {
console.log('resolve');
});
console.log('end');
解析:JavaScript 中存在宏任务和微任务的概念。setTimeout 属于宏任务,Promise.then 属于微任务。在事件循环中,先执行同步任务,所以先打印 start 和 end。然后执行微任务队列中的任务,所以接着打印 resolve,最后执行宏任务队列中的任务,打印 setTimeout。最终输出顺序为 start、end、resolve、setTimeout。
2. Promise.all 的使用
javascript
const promise1 = Promise.resolve(1);
const promise2 = Promise.resolve(2);
const promise3 = Promise.reject(3);
Promise.all([promise1, promise2, promise3])
.then((res) => {
console.log('all then:', res);
})
.catch((err) => {
console.log('all catch:', err);
});
解析:Promise.all 接受一个 Promise 数组作为参数,只有当数组中的所有 Promise 都变为 fulfilled 时,它返回的 Promise 才会变为 fulfilled,并将所有 Promise 的结果组成一个数组作为参数传递给 then 方法的回调函数。只要有一个 Promise 变为 rejected,Promise.all 返回的 Promise 就会变为 rejected,并将第一个被拒绝的 Promise 的理由作为参数传递给 catch 方法的回调函数。这里 promise3 是 rejected 状态,所以最终打印 all catch: 3。
3. Promise.race 的使用
javascript
const promise1 = new Promise((resolve) => {
setTimeout(() => {
resolve(1);
}, 1000);
});
const promise2 = new Promise((resolve) => {
setTimeout(() => {
resolve(2);
}, 500);
});
Promise.race([promise1, promise2])
.then((res) => {
console.log('race then:', res);
})
.catch((err) => {
console.log('race catch:', err);
});
解析:Promise.race 同样接受一个 Promise 数组作为参数,它返回的 Promise 会在数组中的某个 Promise 率先变为 fulfilled 或 rejected 时,跟着变为 fulfilled 或 rejected,并将这个率先改变状态的 Promise 的结果或理由作为参数传递给 then 或 catch 方法的回调函数。这里 promise2 先执行 resolve(2),所以最终打印 race then: 2。
async/await 必考题
- async/await 基本使用
javascript
async function asyncFunc() {
console.log('start asyncFunc');
const result = await Promise.resolve(1);
console.log('result:', result);
return result + 1;
}
asyncFunc().then((res) => {
console.log('final result:', res);
});
解析:async 函数返回一个 Promise 对象。在 async 函数内部,await 只能用于 async 函数中,它会暂停当前 async 函数的执行,等待 await 后面的 Promise 变为 fulfilled 或 rejected,并返回其结果。这里先打印 start asyncFunc,然后等待 Promise.resolve(1) 变为 fulfilled,返回 1 并赋值给 result,接着打印 result: 1,最后返回 result + 1 即 2,并在 asyncFunc().then 中打印 final result: 2。
2. async/await 中的错误处理
javascript
async function asyncErrorFunc() {
try {
console.log('start asyncErrorFunc');
const result = await Promise.reject(1);
console.log('result:', result);
} catch (err) {
console.log('catch error:', err);
}
}
asyncErrorFunc();
解析:在 async/await 中,可以使用 try...catch 来捕获 await 后面 Promise 被拒绝时抛出的错误。这里 Promise.reject(1) 会被 await 捕获,进入 catch 块,所以打印 start asyncErrorFunc 和 catch error: 1。
3. 多个 async/await 并发执行
javascript
async function task1() {
return new Promise((resolve) => {
setTimeout(() => {
resolve('task1 result');
}, 1000);
});
}
async function task2() {
return new Promise((resolve) => {
setTimeout(() => {
resolve('task2 result');
}, 1500);
});
}
async function main() {
const [result1, result2] = await Promise.all([task1(), task2()]);
console.log('result1:', result1);
console.log('result2:', result2);
}
main();
![]()
解析:为了并发执行多个 async 函数,可以将它们的调用放入 Promise.all 中。Promise.all 会等待所有 Promise 都完成,然后将结果以数组形式返回。这里 task1 和 task2 会并发执行,Promise.all 等待它们都完成后,将结果分别赋值给 result1 和 result2,最终打印 result1: task1 result 和 result2: task2 result。
通过对这些 Promise/async/await 必考题的深入学习和理解,相信大家在前端高薪岗的面试中,面对 JS 异步编程相关问题时能够游刃有余。在日常学习和实践中,要不断巩固这些知识,提升自己在异步编程方面的能力,为冲击前端高薪岗打下坚实基础。你在学习过程中对哪部分内容还存在疑问呢?可以随时和我交流,我们一起攻克难点。
更多推荐



所有评论(0)