1.同步与异步
同步:按顺序,代码不中断的执行,常见的:console.log
异步:先执行一部,拿到结果,再执行后续的代码或者回调函数。
1.计时器(setTimeout,setInterval)
2.ajax
3.读取文件
执行顺序:先执行同步代码,再执行异步代码。
console.log(1);
for (let index = 0; index < 1000; index++) {
console.log(index);
}
setTimeout(()=>console.log(2),0);
setTimeout(()=>console.log(3),0);
setTimeout(()=>console.log(4),0);
console.log(5);
执行结果为 1,for循环,5,2,3,4,不管同步带耗时多长,
都是先执行同步代码,因为js是单线程,所以会堵塞,等它执行完,
再执行另一个任务。所以得出一个结论,定时器任务可能是不准时的。
2.process.nextTick
什么时候执行:同步代码执行完,异步代码执行前,示例如下
process.nextTick(()=>{
console.log(1);
})
console.log(2);
setTimeout(() => {
console.log(3);
}, 0);
console.log(4);
执行结果为:
2
4
1
3
3.setImmediate
什么时候执行:异步代码对应的任务队列中,执行完当前的任务,则调用,示例如下
setImmediate(()=>{
console.log(1);
})
console.log(2);
setTimeout(() => {
console.log(3);
}, 0);
setTimeout(() => {
console.log(4);
}, 1000);
setTimeout(() => {
console.log(5);
}, 0);
setTimeout(() => {
console.log(6);
}, 2000);
console.log(7);
执行结果:
2
7
3
5
1
4
6
1.**注意定时器的时间,并不是到点就执行**,而是过多少时间放在任务队列里,
2.因此就可以解释为什么定时器不准时。
3.所以先是执行完同步代码,再过0秒,把定时为0的定时器放入,
4.此时任务队列有任务就会被事件循环给扫描到,就先执行,等当前任务执行完就
执行setImmediate,
5.再过1s,2s,相应的定时器也加入到任务队列中,被扫描到就执行
4.宏任务与微任务
1.异步任务可分为 宏任务与微任务
2.宏任务:计时器,ajax,读取文件
3.微任务:promise.then
4.执行顺序:
* 1.同步程序
* 2.process.nextTick()
* 3.微任务
* 4.宏任务
* 5.setImmediate
示例代码:
setImmediate(()=>{
console.log(1);
})
console.log(2);
setTimeout(() => {
console.log(3);
}, 0);
setTimeout(() => {
console.log(4);
}, 1000);
setTimeout(() => {
console.log(5);
}, 0);
new Promise((resolve)=>{
console.log(6);
resolve();
}).then(()=>
{console.log(7);
}
)
process.nextTick(()=>{
console.log(8);
})
结果:
2
6
8
7
3
5
1
4
5.Promise和async和await
Promise:
先看代码:
let fn2=new Promise(()=>{
console.log(1);
})
fn2.then(()=>{
console.log(2);
})
输出结果为1,没有2,因为Promise里面没有调用resolve方法,所以不会
执行then方法,而且resolve里面的数据是then里面函数的形参
let fn2=new Promise((resolve)=>{
console.log(1);
resolve(2);
})
fn2.then((data)=>{
console.log(data);
console.log(3);
})
执行结果为1,2,3
async:
先看一个方法加入async后的代码以及执行结果:
async function fun() {
return 1;
}
let fn=fun();
console.log(fn);
结果:
Promise { 1 }
说明:async 返回值是个Promise对象
Promise后面可以接then,我们来看下运行效果
async function fun() {
return 1;
}
let fn=fun();
fn.then((data)=>{
console.log(data);
});
结果:
1
所以可以看到这段代码等价于
let fn2=new Promise((resolve)=>{
resolve(1);
})
fn2.then((data)=>{
console.log(data);
})
可以看到到async本质就是Promise的语法糖
await
async一般与await成对出现,await后面接的也是Promise对象,await
只在异步函数里面才起作用,它会暂停代码在该行上,直到 promise 完成,
然后返回结果值(是获得resolve里的值)
function fn2(){
return new Promise((resolve)=>{
resolve(1);
})
}
function fn1(){
return new Promise((resolve)=>{
resolve(2);
})
}
async function fun3(){
let a=await fn1();
console.log(3);
let b=await fn2();
//await这后面的代码可以理解为是在then里面的
console.log(a,b);
console.log(4);
}
fun3();
结果:
3
2 1
4
下面是道执行顺序的例题,大家可以试着去做一下
console.log(1);
async function async1(){
await async2()
console.log(2);
}
async function async2() {
console.log(3);
}
async1();
setTimeout(() => {
console.log(4);
}, 0);
new Promise(resolve=>{
console.log(5);
resolve();
}).then(()=>{
console.log(6);
}).then(()=>{
setTimeout(() => {
console.log(7);
}, 100);
})
console.log(8);
结果:
1
3
5
8
2
6
4
7