简单叙述一下什么是事件循环
还是拿之前的餐厅来举例,我们去点了个番茄炒蛋,服务生告诉后厨做一个番茄炒蛋,张三也去了餐厅,点了个麻辣小龙虾,服务生又告诉后厨做一份麻辣小龙虾,小李也去了,点了个蛋炒饭。
解析一下这个情景,餐厅是一个事件循环,其中我们的点餐叫做线程。服务生第一个把我要的番茄炒蛋端过来了,于是我的线程结束了,因为麻辣小龙虾做的慢,蛋炒饭做完了,服务生又给小李端上来了蛋炒饭,小李虽然是后来的,但是他的过程要比张三快,最后小龙虾好了,服务生给张三端上来小龙虾,至此三个线程都结束了。
用代码实现一个简易版的事件循环
const eventloop = {
// 事件队列
queue: [],
loop(){
while(this.queue.length){
// 如果有事件就进行处理
var callback = this.queue.shift();
callback();
}
// 每50毫秒会检测一下事件
setTimeout(this.loop.bind(this),50);
},
// 添加事件
add(callback){
this.queue.push(callback);
}
}
eventloop.loop();
// 分别在 500毫秒跟800毫秒,往队列中加入两个事件
setTimeout(()=>{
eventloop.add(function(){
console.log('第一个');
})
},500)
setTimeout(()=>{
eventloop.add(function(){
console.log('第二个');
})
},800)
有话说
当然,在真实情况中会比这复杂的多,不会每50毫秒去检测一次,要快的多,添加的事件也不会只有回调函数,例如一些文件读写操作等。我们的事件队列可能还会有文件处理队列,定时操作队列等多种不同的队列。
callback
回调函数格式规范
- error-first callback
- Node-style callback
- 第一个参数是error,后面的参数才是结果
场景
你在面试之后,面试官让你回去等消息。
结果:
- 过
- 不过
ps:面试过了我们就笑一下,面试不过我们就哭!
先上代码:
interview(function(err){
if(err){
return console.log('cry at 1st');
}
interview(function(err){
if(err){
return console.log('cry at 2nd');
}
interview(function(err){
if(err){
return console.log('cry at 3rd');
}
console.log('smile');
});
})
})
function interview(callback) {
setTimeout(()=>{
if(Math.random() < 0.8){
callback('success');
} else {
callback( new Error('fail'));
}
},1000)
}
这是一个正常的面试流程:
- 一面------>挂掉
- 一面------->二面------>挂掉
- 一面------->二面------>三面------>挂掉
- 一面------->二面------>三面------>入职
看是看着这种嵌套是真的恶心,这种问题就叫做回调地狱
,这也是比较容易出现在异步中的问题,另外一个问题就是并发了,我们用同时面试两家公司为例,毕竟这也是正常能够出现的现象。
这时候张三说了:我会写我会写,还是上面代码的理念,我加一个计数器,面试过了就count++,count为2的时候,就证明两个面试都过了,这样可以用if判断并写一些逻辑。
简单描述一下张三的代码结构:
var count = 0;
interview(function (err) {
if(err){
return console.log('cry');
}
count++
})
interview(function (err) {
if(err){
return console.log('cry');
}
count++
if(count){
}
})
大致是这个样子,看起来很麻烦。这个问题就涉及到异步流程控制问题,也就是异步的并发,针对这个问题,我们强大的社区当然是有解决方案的。
- npm包:
async.js
- thunk编程方式
现在好像这两个方式都不用了😭