一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第11天,点击查看活动详情。
前言
正直铜三铁四,本菜鸡也参与了一些面试,发现现在的面试题玩得真变态出得挺好的啊,前两天面试过程中碰到这样一道问答题;题目:
const foo = ()=>new Promise((resolve,reject)=>{
for(var i = 0;i<3;i++){
if(i==2){
reject(i)
}
else{
resolve(i)
}
}
})
setTimeout(()=>{
console.log('output')
})
foo().then((i)=>{
console.log('resolve',i)
}).catch(()=>{
console.log('reject',i)
})
问输出结果
我当时草草扫一眼,一看这不就是考事件循环吗,这玩意我太熟了;
然后定睛一看,发现事有蹊跷,这个promise里面循环resolve最后还reject是个什么骚操作,实际开发中这么写不得挂路灯?
于是我挠头一通分析:
-
.then微任务优先于setTimeOut先执行这个不用多想,output一定是在后面输出 -
我记得Promise有三个状态:
pending、fulfilled和rejected,一旦fulfilled``或rejected掉了状态就不会再变了,所以.catch应该不会触发 -
多次
resolve,状态是没变的,那值会不会覆盖前面的值呢,这我还真不太清楚,毕竟也没谁会在Promise里多次resolve啊
就在这个时候,我注意到for循环里是var i,为什么是var i不是let i呢,一定有问题!于是我又想到这个经典老题:
for(var i = 0;i<3;i++){
setTimeout(()=>console.log(i)); // 3 3 3
}
众所周知,这题改为let就能正常输出0 1 2,考的是函数作用域/块级作用域,我当时就觉得有点像,异步+for(var),buff一致,四舍五入这就是一样的题目!
于是我自信的回答了resolve,3 output,面试官啥也没说就下一题了;我后来自己试了一下:结果是
resolve,0 output
非常尴尬
解析
于是我又仔细看了promise/A+规范,上面写着:
当进入完成状态之后,不会再转变为任何状态,且会有一个不会改变的值,所以resolve时的值是不会变得;reject也一样;
其实这里即便按照形参传参,这个值也应该是0,当时没想清楚就草草作答了
记录一下,加深对promise的理解