面试题答案
一键面试1. Promise 的状态转换
- Promise 有三种状态:
pending
(进行中)、resolved
(已完成,又称fulfilled
)和rejected
(已拒绝)。 - 状态只能从
pending
转换为resolved
或rejected
,且状态一旦改变,就不会再变。
2. 事件循环机制
JavaScript 是单线程语言,通过事件循环(Event Loop)机制来处理异步操作。事件循环会不断检查调用栈(Call Stack)和任务队列(Task Queue)。
- 宏任务(Macrotask):包括
script
(整体代码)、setTimeout
、setInterval
、setImmediate
(Node.js 环境)、I/O
、UI rendering
等。 - 微任务(Microtask):包括
Promise.then
、process.nextTick
(Node.js 环境)、MutationObserver
等。
3. Promise 状态转换与事件循环的相互影响
当一个 Promise 从pending
转换为resolved
或rejected
时,它的.then
回调函数会被放入微任务队列。事件循环机制会在当前调用栈清空后,优先处理微任务队列中的任务,处理完微任务队列后,再从宏任务队列中取出一个任务放入调用栈执行,如此循环。
4. 代码示例
console.log('start');
setTimeout(() => {
console.log('setTimeout');
}, 0);
Promise.resolve()
.then(() => {
console.log('Promise.then');
});
console.log('end');
执行顺序分析
console.log('start')
执行,输出start
。setTimeout
的回调函数被放入宏任务队列。Promise.resolve().then
的回调函数被放入微任务队列。console.log('end')
执行,输出end
。- 此时调用栈清空,事件循环开始处理微任务队列,
Promise.then
的回调函数执行,输出Promise.then
。 - 微任务队列清空,事件循环从宏任务队列中取出
setTimeout
的回调函数放入调用栈执行,输出setTimeout
。
所以最终输出顺序为:start
、end
、Promise.then
、setTimeout
。