前言
今天去面试NodeJS的时候面试官问了关于Promise和Event Loop相关的问题
虽然平时操作经常用到但实际被问的时候还是解释的不太清楚
其中最让我印象深刻的问题是Promise用在哪里
我的回答是Promise是非同步操作,为了避免耗时的操作堵塞Process
结果被纠正说Promise应该是同步,觉得很怪所以回家整理了一下这方面的资料
其实这个问题已经有很多详解了,不过想说整理一遍,对自己的观念也比较清晰
如果有错欢迎指教
内文
Promise和Event Loop其他的文章应该有更详细的说明,这里不多做赘述。
直接上code:
var fs = require('fs');function test(){ console.log(1); let promise = new Promise((reslove,reject)=>{ let data = fs.readFileSync(`${__dirname}/package.json`); reslove(6); console.log(2); }); setTimeout(()=>{console.log("x")},0); console.log(3); promise.then((s)=>{ console.log(s); }); console.log(4); for(let i = 0; i<100;i++){ let data = fs.readFileSync(`${__dirname}/package.json`); } return 5;};console.log(test());function a(){ return 0;}console.log(a());
输出结果:
1234506x
发生了什么
我们可以先从Event Loop的机制了解
大致上分为六个阶段:
这六个阶段根据官方概述:
1.定时器:本阶段执行已经被 setTimeout() 和 setInterval() 的调度回调函数。2.待定回调:执行延迟到下一个循环迭代的 I/O 回调。3.idle, prepare:仅系统内部使用。4.轮询:检索新的 I/O 事件;执行与 I/O 相关的回调(几乎所有情况下,除了关闭的回调函数,那些由计时器和 setImmediate() 调度的之外),其余情况 node 将在适当的时候在此阻塞。5.检测:setImmediate() 回调函数在这里执行。6.关闭的回调函数:一些关闭的回调函数,如:socket.on('close', ...)。
根据上面的说明可以很清楚的了解到,基本上callback的执行阶段会落在第六步骤
因此当函式都Return完毕后才会轮到callback
所以在第四步骤输出123450
第六步骤输出6
而x是由于是setTimeout()的callback产生的行为
在使用的当下他会属于次轮循环
因为使用当下已经处于第四步骤,而setTimeout的callback属于第一步骤
于是等到次轮循环的时候才会将x显示出来
结论
至于为什么面试官会说Promise会是同步操作的原因,事后打电话回去了解。
才知道原来他指的是建构Promise当下= ="(汗
但基本上Promise都是用于非同步操作,在大多数的事件结束后才去执行这个事情
这样的好处以网站来说,假设用户进行了一个转档的操作并且要显示在前端
可以先渲染前端页面,而转档这件大事,则是在渲染完前端后,再去执行
执行完毕后,再透过AJAX或是其他方式去更新用户的页面。
不必等到后端转档完毕 才一次把所有物品都丢到前端