参考文章: js 异步执行顺序
 
1.js的执行顺序,先同步后异步
2.异步中任务队列的执行顺序: 先微任务microtask队列,再宏任务macrotask队列
3.调用Promise 中的resolve,reject属于微任务队列,setTimeout属于宏任务队列
注意以上都是 队列,先进先出。
 
微任务包括 `process.nextTick` ,`promise` ,`MutationObserver`。
宏任务包括 `script` , `setTimeout` ,`setInterval` ,`setImmediate` ,`I/O` ,`UI rendering`。
 
题目1:
console.log('script start')
async function async1() {
await async2()
console.log('async1 end')
}
async function async2() {
console.log('async2 end')
}
async1() setTimeout(function() {
console.log('setTimeout')
}, 0) new Promise(resolve => {
console.log('Promise')
resolve()
})
.then(function() {
console.log('promise1')
})
.then(function() {
console.log('promise2')
}) console.log('script end')

执行结果?

分析:

首先执行 同步代码:

1. 首先执行    console.log('script start')
2. 执行 async1() 的时候,马上执行了 async2函数:console.log('async2 end')

3. 顺序执行 new Promise()中的同步函数:console.log('Promise')
4. 最后执行  console.log('script end')。
上面是同步执行的代码,然后看剩下的异步执行的代码:
首先,setTimeout是 宏观任务,排除到最后,剩下微观任务:
async function async1() {
await async2()
console.log('async1 end')
}
new Promise(resolve => {
resolve()
})
.then(function() {
console.log('promise1')
})
.then(function() {
console.log('promise2')
})

5. 然后根据先入先出的对列方式,先执行  await async2() 后面阻碍的函数  console.log('async1 end')

6. 执行promise的resolve函数

new Promise(resolve => {
resolve()
})

也就是接下来的两个then: console.log('promise1') ----  console.log('promise2') ;

7. 最后执行的是 setTimeout函数  console.log('setTimeout') ;

综上所述,以上代码执行的顺序是:

1.script start 2.async2 end 3.Promise 4.script end 5.async1 end 6.promise1 7.promise2 8.setTimeout

题目2:

(function() {

    setTimeout(() => {
console.log(0);
}); new Promise(resolve => {
console.log(1); setTimeout(() => {
resolve();
Promise.resolve().then(() => console.log(2));
console.log(3);
}); Promise.resolve().then(() => console.log(4)); }).then(() => {
console.log(5);
Promise.resolve().then(() => console.log(8));
setTimeout(() => console.log(6));
}); console.log(7); })();

1. 同样先执行同步代码,且先把setTimeout去掉:

new Promise(resolve => {
console.log(1);
Promise.resolve().then(() => console.log(4)); //微观任务
}).then(() => { //then函数是执行对应的 resolve 的时候才执行的
console.log(5);
Promise.resolve().then(() => console.log(8));//微观任务
}); console.log(7);

可以看出先执行: console.log(1);console.log(7);

2. 执行微任务  Promise.resolve().then(() => console.log(4));

代码变成了:

(function() {
setTimeout(() => {
console.log(0);
});
new Promise(resolve => {
setTimeout(() => {
resolve();
Promise.resolve().then(() => console.log(2));
console.log(3);
});
}).then(() => {
console.log(5);
Promise.resolve().then(() => console.log(8)); //这句是多加的
setTimeout(() => console.log(6));
});
})();

只剩下宏观任务(微观任务在宏观任务里,也就是宏观任务外面不在有微观任务了)

3. 执行  console.log(0);

4.再执行 new Promise 中的  setTimeout,先执行里面的同步函数:console.log(3)

5. 再执行上面的 resolve,对应的是下面的then函数:

then(() => {
console.log(5);
Promise.resolve().then(() => console.log(8)); //这句是多加的
setTimeout(() => console.log(6));
}

所以先执行 console.log(5);

剩下的都是微观任务和宏观任务,先看微观任务:

 new Promise(resolve => {
resolve();
Promise.resolve().then(() => console.log(2));
}).then(() => {
Promise.resolve().then(() => console.log(8));
setTimeout(() => console.log(6));
});

所以根据队列中的微观任务顺序先执行:console.log(2),在执行then中的 console.log(8);

最后再执行 console.log(6)

综上所述,结果为

1/7/4/0/3/5/2/8/6
 
详细问题三:
(function() {
setTimeout(() => {
console.log(0);
}); new Promise(resolve => { console.log(1); setTimeout(() => {
resolve();
Promise.resolve().then(() => {
console.log(2);
setTimeout(() => console.log(3));
Promise.resolve().then(() => console.log(4));
});
}); Promise.resolve().then(() => console.log(5)); }).then(() => { console.log(6);
Promise.resolve().then(() => console.log(7));
setTimeout(() => console.log(8)); }); console.log(9);
})();
解释如下:【同步>异步;微任务>宏任务】
第一步:打印出1、9 ;如图

                    图a

由图a中的任务队列可知:
第二步: 执行微任务3,打印出 
第三步:执行宏任务1,打印出 
第四步:开始执行宏任务2;如图:

                              图b

第五步:由图b中的任务队列可知, 执行微任务4,打印出 6,如图:

                              图c

第六步:由图c中的任务队列可知, 执行微任务5,打印出;如图

                              图d

由图d的任务队列可知,
第七步:执行微任务6,打印出
第八步:执行微任务9,打印出
第九步:执行宏任务7,打印出8;
第十步:执行宏任务8,打印出3;

即答案是:

1-9-5-0-6-2-7-4-8-3

js 异步执行顺序的更多相关文章

  1. 浅析js的执行顺序

    javascript是一种描述型的脚本语言,是一种解析语言,由浏览器动态解析,不同种类的浏览器不同版本的浏览器对于js的解析有着微小的差别,不同浏览器的js解析引擎效率也有高低,下面来给大家分析一下j ...

  2. js代码执行顺序问题

      前  言 LiuDaP 今天就给大家介绍一个特别基础的东西,javascript中函数的一点儿小知识(js代码的执行顺序),希望对大家有那么一点点帮助吧!!! 一.js--->单线程 严格意 ...

  3. 浅析JS异步执行机制

    前言 JS异步执行机制具有非常重要的地位,尤其体现在回调函数和事件等方面.本文将针对JS异步执行机制进行一个简单的分析. 从一份代码讲起 下面是两个经典的JS定时执行函数,这两个函数的区别相信对JS有 ...

  4. 关于js事件执行顺序

    关于js事件执行顺序小技巧 js事件执行顺序是js中一个老生常谈的一个话题, 聊这个话题之前我们先谈谈怎么给页面元素绑定我们需要的事件 1.给页面元素绑定事件 a)直接在元素上面加上需要绑定的事件,如 ...

  5. [js]js代码执行顺序/全局&私有变量/作用域链/闭包

    js代码执行顺序/全局&私有变量/作用域链 <script> /* 浏览器提供全局作用域(js执行环境)(栈内存) --> 1,预解释(仅带var的可以): 声明+定义 1. ...

  6. 关于js事件执行顺序小技巧

    js事件执行顺序是js中一个老生常谈的一个话题, 聊这个话题之前我们先谈谈怎么给页面元素绑定我们需要的事件 1.给页面元素绑定事件 a)直接在元素上面加上需要绑定的事件,如 <button ty ...

  7. js异步执行 按需加载 三种方式

    js异步执行 按需加载 三种方式 第一种:函数引用 将所需加载方法放在匿名函数中传入 //第一种 函数引用 function loadScript(url,callback){ //创建一个js va ...

  8. JS异步执行之setTimeout 0的妙用

    最近在工作中遇到一些问题,大致是关于js执行问题的.由于没搞清执行顺序,导致出现了一些奇怪的bug. 所以这里整理一些有关异步执行的知识(冰山一角角)... 大家都知道js是单线程的,执行起来是顺序的 ...

  9. 前端知识总结--js异步事件顺序

    js中异步事件中容易混淆的 Promise 和 setTimeout 的执行顺序是怎样的? setTimeout(() => console.log(1), 0); new Promise(fu ...

随机推荐

  1. 常见问题:Web/Servlet生命周期与Spring Bean生命周期

    Servlet生命周期 init()初始化阶段 Servlet容器加载Servlet(web.xml中有load-on-startup=1;Servlet容器启动后用户首次向Servlet发请求;Se ...

  2. 洛谷 题解 UVA247 【电话圈 Calling Circles】

    [题意] 如果两个人互相打电话(直接或者间接),则说他们在同一个电话圈里.例如,\(a\)打给\(b\),\(b\)打给\(c\),\(c\)打给\(d\),\(d\)打给\(a\),则这四个人在同一 ...

  3. sshd_config参数说明

    SSHD_CONFIG(5) OpenBSD Programmer's Manual SSHD_CONFIG(5)名称 sshd_config - OpenSSH SSH 服务器守护进程配置文件大纲 ...

  4. hdoj4099(字典树+高精度)

    题目链接:https://vjudge.net/problem/HDU-4099 题意:给T组询问,每个询问为一个字符串(长度<=40),求以该字符串为开始的fibonacci数列的第一个元素的 ...

  5. Linux将.deb以绿色免安装的方式“安装”

    1.如果是xxx.deb文件,一般网上都是教你dkpg -i xxx.deb,但是这种方式类似windows里的安装,可能会在很多地方生成一些“垃圾”数据[比如不需要在dpkg安装应用信息文件里写入此 ...

  6. phpstrom xdebug phpstudy调试,跳不到设置断点的原因,以及配置方法

    设置的是127 的地址,而用localhost 方式请求,所以无法跳到断点 环境 phpstudy 2018 php 7.2.10 xdebug版本 (因为要与php版本要对应,注意别选错了,我的用的 ...

  7. 使用AOP进行权限验证

    首先我们定义一个切入点(匹配com.ed.controller.Seller开头的controller的所有public方法) @Pointcut("execution(public * c ...

  8. Python03之单引号、双引号、三单引号、三双引号

    今天在学习字符串的时候,发现字符串有时使用单引号,有时使用双引号,而有时还使用三引号.至此我整理如下: 单引号和双引号区别.三单引号和三双引号也没什么区别. 一: 两单引号之间不可以出现单引号,如果出 ...

  9. Ubuntu 18.04安装arm-linux-gcc交叉编译器

    Ubuntu 18.04安装arm-linux-gcc交叉编译器

  10. golang 上传文件(包括 gin 实现)

    golang web服务有时候需要提供上传文件的接口,以下就是具体示例.为了示例简单(吐槽下 golang 的错误处理), 忽略了所有的错误处理.本文会用两种方式(标准库和gin)详细讲解 golan ...