在学明白事件循环机制之前,需要先明白几个概念。
js中的任务分为同步任务和异步任务两种。
我们正常所写的按照顺序解释执行的代码都是同步任务,换句话说,代码当即就可以执行并不需要等待的都是同步任务。
而异步任务概念正好相反,需要等待一段时间执行的,或者说间隔一段时间执行的,像setTimeout,setInterval以及http请求等等,执行时和时间挂钩的任务,都是异步任务。
同步任务和异步任务最大的不同就是,同步任务是立即执行的,异步任务不是立即就执行的
异步任务又分为宏任务和微任务两种。
宏任务:异步任务当中执行优先级比较低的任务,setTimeout,steInterval,ajax,promise等都是宏任务。
微任务:部分同步任务执行时会附带微任务,微任务的执行发生在所有同步任务执行结束后,紧接着执行。要注意不是所有的同步任务都会附带微任务,只有一部分,目前为止只有两个同步任务会附带微任务,第一个是promise的then方法是微任务,第二个是node中process.nextTick()方法。
就像日常生活一样,你需要对你做的事情有安排。
js中对于任务的安排也在模拟现实生活。
我们来举一个例子,某天你结束了一天疲惫的工作下班回家,你进门先打开了热水器,因为你想吃完晚饭去洗澡。但是烧热水是个需要耗费时间的活,你不可能一直等待。于是乎你开始准备做饭,
假设今晚你吃老北京炸酱面,你正常的做法一定是先煮面条,趁着煮面条的时间去把炸酱和黄瓜丝胡萝卜丝准备好,等面条煮熟了把炸酱放上,大功告成。
好,请注意在以上的例子中,你做了三件事,烧热水,煮面,准备炸酱。
请你思考,上面三件事哪一件事不需要等待,直接就可以做,毫无疑问准备炸酱
哪一件事需要等待,但是一旦到了时间就必须立即执行,那当然是煮面条
那么烧热水洗澡这件事,虽然需要等待,但是并不一定要立即执行。
上面三件事分别对应js中的同步任务,微任务,宏任务。
所以我们也不难排列出优先级顺序:同步任务>微任务>宏任务
看下面这段代码的执行结果:
function app(){
console.log(1);
setTimeout(function(){
console.log(4);
},0)
new Promise((resolve,reject)=>{
//这里执行的是同步任务,
console.log(2);
resolve();
}).then((value,reason)=>{
//这里是微任务
console.log(3);
}
)
console.log(5);
}
app();
毫无疑问执行结果应该是:
1
2
5
3
4
1,2,5都是同步任务,3是微任务,4是宏任务
js在执行任务的时候,会优先执行同步任务,把宏任务和微任务都分别放在一旁,宏任务会放在宏任务队列,微任务会放在微任务队列,当同步任务执行完成之后,会优先去微任务队列寻找需要执行的微任务,等待微任务执行完成之后才会去找宏任务队列,进一步执行宏任务。
以上就是事件循环机制的内容。
明白了这个道理之后,再来看一下下面这段代码的执行结果:
function app(){
console.log(1);
setTimeout(function(){
console.log(2);
},0)
new Promise((resolve,reject)=>{
//这里执行的是同步任务,
console.log(3);
resolve();
}).then((value,reason)=>{
//这里是微任务
console.log(4);
}
)
console.log(5);
new Promise((resolve,reject)=>{
//这里执行的是同步任务,
console.log(6);
resolve();
}).then((value,reason)=>{
//这里是微任务
console.log(7);
}
)
}
app();
结果自然是:
1
3
5
6
4
7
2
我们研究事件循环机制有什么用呢?它能够帮助我们解决很多在开发过程中的问题。
来看一段代码:
var result=[];
$.ajax({
type:'GET',
url:url,
success:data=>{
//假设我在这里请求回来一个数组data
result=data;
}
})
console.log(result);
大家觉得执行结果是什么?
很显然是[ ],为什么?因为ajax是一个异步请求,是一个宏任务,当你打印result的时候它并没有请求成功,所以你没办法把请求回来的值赋给result,那么怎么办呢?最简单的办法就是加一个属性async:false,将ajax请求改为同步任务。
涉及到异步请求的例子其实都可以这样解决,再例如我们现在有这么一个需求,写一个函数,请求一段json,当我每次调用这个函数的时候请求回来一段json,return给我,要求用axios。
我们就可以这样做:
//引入axios,因为我是node环境,所以这样写
var axios=require("axios");
function app(){
return new Promise((resolve,reject)=>{
//请求外面套一层promise
axios({
method:'get',
url:'http://localhost:9000/xzqservice/geomtry/330000'
}).then(res=>{
resolve(res.data);
}
)
})
}
async function getData(){
let data= await app();
console.log(data);
}
getData();