• 个人理解

前景-代码输出结果是什么

我们都知道,循环队列的时候,同步任务大于异步任务(异步任务里面的微任务又大于宏任务),那么你猜猜这个代码输出结果是 什么呢

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script>
setTimeout(() => {
console.log(1);
}, 0);

new Promise(function(resolve,reject){
console.log(2);
resolve();
console.log(3);
}).then(function(){
console.log(4);
}).finally(function(){
console.log(5);
});
console.log(6);
</script>
  • 做出来了吗?我公布下答
  • 答案
1
2 3 6 4 5 1 

前景解析

  • 首先,你知道同步>异步,可是可能不太会区分同步和异步,其实记住下面的异步任务就好,其他就都是同步任务了

  • 异步任务:setTimeout,setInterval,setImmediate(非标准),I/O,UI rendering,Promise

  • 你们肯定也知道,promise的优先级大于其他异步任务,因为Promise是微任务嘛

  • 但是呢,这里说promise是异步任务其实不完全对,因为创建promise的时候是同步执行的,nextTick才是异步执行的(也就是.then,.catch这种方法),下面的例子和前景例子很好的说明了这个情况

    1
    2
    3
    4
    5
    6
    7
    8
    new Promise(resolve=>{
    console.log(1);
    resolve(3);
    }).then(num=>{
    console.log(num);
    });
    console.log(2);
    //依次为 123

我们学习了上面的点,再来看看Promise.all方法

  • 在之前的时候,我一直想不明白,Promise.all方法为什么能做到将多个promise封装成为一个新的promise实例,并同步获取到结果,现在才知道原因,先看下面代码,后面再详细解释
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  <script src="https://cdn.bootcdn.net/ajax/libs/axios/1.1.3/axios.min.js"></script>
<script>
let work1 = new Promise((resolve,reject)=>{
resolve(axios.get('https://api.oick.cn/dutang/api.php'))
});

let work2 = new Promise((resolve,reject)=>{
resolve(axios.get('https://api.oick.cn/yiyan/api.php'))
});

let work3 = new Promise((resolve,reject)=>{
resolve(axios.get('https://api.oick.cn/dog/api.php'))
});
Promise.all([work1,work2,work3]).then(res=>{
console.log(res);
})
</script>
  • 看着上面的代码,我一直在想,这为什么可以做到并发,我想想中的并发是这个请求同一时间发送,但是我搜来搜去,Promise.all 可以同时请求多个接口,这句话是错误的~我后面也调试发现并不是在同一时间发送ajax请求的,而是顺序发送,最后统一处理返回的结果

  • 我们知道,js是单线程的,所以分为同步和异步,我们创建promise的时候是同步执行的,nextTick才是异步执行的,所以Promise里面的函数是同步任务

1
2
3
4
5
6
7
8
9
let work1 = new Promise((resolve,reject)=>{
//同步任务
resolve(axios.get('https://api.oick.cn/dutang/api.php'))
});

let work2 = new Promise((resolve,reject)=>{
//同步任务
resolve(axios.get('https://api.oick.cn/yiyan/api.php'))
});
  • 所以在没有调用promise.all之前,ajax请求已经被发送了,只不过在promise.all的.then才统一接收处理

可以看到,如果是统一时间发送的,我在调试的时候应该说Promise.all才执行ajax发送请求,但是我在经过let work2的时候停顿一会后才执行let work3处的代码**,然后才准备执行**promise.all方法, 就会发现,前几天的数据请求状态为200了,也是在promise.all之前就发送了这个请求,而不是说执行promise.all这代码的时候才发送ajax请求

  • 等待了很久后,终止调试,发现正常输出返回的结果,而没有超时,所以就说明不是在promise.all才发送请求,而是我们在promise.all做最终处理