先来一道关于async/await、promise和setTimeout的执行顺序的题目:

 async function async1() {
console.log('async1 start');
await async2();
console.log('asnyc1 end');
}
async function async2() {
console.log('async2');
}
console.log('script start');
setTimeout(() => {
console.log('setTimeOut');
}, 0);
async1();
new Promise(function (reslove) {
console.log('promise1');
reslove();
}).then(function () {
console.log('promise2');
})
console.log('script end');

执行结果:

 script start
async1 start
async2
promise1
script end
asnyc1 end
promise2
setTimeOut

首先,我们先来了解一下基本概念:

js EventLoop 事件循环机制:

JavaScript的事件分两种,宏任务(macro-task)和微任务(micro-task)

  • 宏任务:包括整体代码script,setTimeout,setInterval
  • 微任务:Promise.then(非new Promise),process.nextTick(node中)

  事件的执行顺序,是先执行宏任务,然后执行微任务,这个是基础,任务可以有同步任务和异步任务,同步的进入主线程,异步的进入Event Table并注册函数,异步事件完成后,会将回调函数放入Event Queue中(宏任务和微任务是不同的Event Queue),同步任务执行完成后,会从Event Queue中读取事件放入主线程执行,回调函数中可能还会包含不同的任务,因此会循环执行上述操作。
  注意: setTimeOut并不是直接的把你的回掉函数放进上述的异步队列中去,而是在定时器的时间到了之后,把回掉函数放到执行异步队列中去。如果此时这个队列已经有很多任务了,那就排在他们的后面。这也就解释了为什么setTimeOut为什么不能精准的执行的问题了。setTimeOut执行需要满足两个条件:

  1. 主进程必须是空闲的状态,如果到时间了,主进程不空闲也不会执行你的回掉函数
  2. 这个回掉函数需要等到插入异步队列时前面的异步函数都执行完了,才会执行

简单理解就是:

  了解了什么是宏任务和微任务,就好理解多了,首先执行 宏任务 => 微任务的Event Queue => 宏任务的Event Queue

promise、async/await

  1. 首先,new Promise是同步的任务,会被放到主进程中去立即执行。而.then()函数是异步任务会放到异步队列中去,那什么时候放到异步队列中去呢?当你的promise状态结束的时候,就会立即放进异步队列中去了。
  2. 带async关键字的函数会返回一个promise对象,如果里面没有await,执行起来等同于普通函数;如果没有await,async函数并没有很厉害是不是
  3. await 关键字要在 async 关键字函数的内部,await 写在外面会报错;await如同他的语意,就是在等待,等待右侧的表达式完成。此时的await会让出线程,阻塞async内后续的代码,先去执行async外的代码。等外面的同步代码执行完毕,才会执行里面的后续代码。就算await的不是promise对象,是一个同步函数,也会等这样操作

步入正题:

根据图片显示我们来整理一下流程:

  1. 执行console.log('script start'),输出script start;
  2. 执行setTimeout,是一个异步动作,放入宏任务异步队列中;
  3. 执行async1(),输出async1 start,继续向下执行;
  4. 执行async2(),输出async2,并返回了一个promise对象,await让出了线程,把返回的promise加入了微任务异步队列,所以async1()下面的代码也要等待上面完成后继续执行;
  5. 执行 new Promise,输出promise1,然后将resolve放入微任务异步队列;
  6. 执行console.log('script end'),输出script end;
  7. 到此同步的代码就都执行完成了,然后去微任务异步队列里去获取任务
  8. 接下来执行resolve(async2返回的promise返回的),输出了async1 end。
  9. 然后执行resolve(new Promise的),输出了promise2。
  10. 最后执行setTimeout,输出了settimeout。

参考博客:https://blog.csdn.net/yun_hou/article/details/88697954

关于async/await、promise和setTimeout执行顺序的更多相关文章

  1. Promise和setTimeout执行顺序 面试题

    看到过下面这样一道题: (function test() { setTimeout(function() {console.log(4)}, 0); new Promise(function exec ...

  2. promise 及 setTimeout 执行顺序

    setTimeout(function() { console.log(1); }, 0); new Promise(function(res, rej) { res(2); console.log( ...

  3. promise和setTimeout执行顺序的问题

    提出问题,问题代码为 setTimeout(function(){console.log(1)},0); new Promise(function(resolve){ console.log(2) f ...

  4. async await promise 执行时序

    先用一个例子来说明async await promise的执行顺序 console.log('start'); async function test(){ console.log('111'); a ...

  5. 理解koa2 之 async + await + promise

    koa是下一代的Node.js web框架. 我们首先使用koa来实现一个简单的hello world吧!假如目前的项目结构如下: ### 目录结构如下: koa-demo1 # 工程名 | |--- ...

  6. 浅谈循环中setTimeout执行顺序问题

    浅谈循环中setTimeout执行顺序问题 (下面有见解一二) 期望:开始输出一个0,然后每隔一秒依次输出1,2,3,4. for (var i = 0; i < 5; i++) { setTi ...

  7. async await promise

    async 异步函数,以后可能会用得很广. 1.箭头函数: 没有{ }时不写return 也有返回值 2.Promise : 异步神器,很多异步api都是基于Promise 3.new Promise ...

  8. 一种通过async/await实现函数同步执行的方式

    const testArr = [ () => { return new Promise((resolve, reject) => { setTimeout(()=> { alert ...

  9. Async/await promise实现

    An async function can contain an await expression that pauses the execution of the async function an ...

随机推荐

  1. 力扣(LeetCode)二进制求和 个人题解

    给定两个二进制字符串,返回他们的和(用二进制表示). 输入为非空字符串且只包含数字 1 和 0. 示例 1: 输入: a = "11", b = "1" 输出: ...

  2. bash:加减乘除(bc、let)

    bc *. echo "$2 * $2" | bc > file let 如果只是 let a=1 和 a=1,它们没有区别,但是 let 还可以用于带赋值的运算,例如 le ...

  3. JavaScript中的基本数据类型和引用数据类型

    ECMAScript变量包括了两种不同的数据类型 在学习JavaScript的数据类型时,我们通常会把数据类型分成六中(官方认为)Object.String.Boolean.Number.Undefi ...

  4. 关于PHP中依赖注入的详细介绍

    依赖注入原理: 依赖注入是一种允许我们从硬编码的依赖中解耦出来,从而在运行时或者编译时能够修改的软件设计模式.简而言之就是可以让我们在类的方法中更加方便的调用与之关联的类. 实例讲解: 假设有一个这样 ...

  5. Three.js - 走进3D的奇妙世界

    本文将通过Three.js的介绍及示例带我们走进3D的奇妙世界. 文章来源:宜信技术学院 & 宜信支付结算团队技术分享第6期-支付结算部支付研发团队前端研发高级工程师-刘琳<three. ...

  6. springboot+logback日志输出企业实践(下)

    目录 1.引言 2. 输出 logback 状态数据 3. logback 异步输出日志 3.1 异步输出配置 3.2 异步输出原理 4. springboot 多环境下 logback 配置 5. ...

  7. python爬虫项目-一见倾心壁纸

    方法1 import re import urllib import urllib.request def getHtml(url): page = urllib.request.urlopen(ur ...

  8. python常见字符串操作

    附: python2.x和python3.x中raw_input( )和input( )区别: 备注:1.在python2.x中raw_input( )和input( ),两个函数都存在,其中区别为r ...

  9. Android Binder机制介绍

    做过Android开发的同学可能有些体会,入门初期,工作内容主要是实现各式各样的UI界面,以及实现应用的业务逻辑.在这个阶段,我们会逐渐熟悉View系统,逐渐学会实现各种各样的界面以及动画效果.再往后 ...

  10. 针对可变类型的for遍历

    针对可变类型的for遍历 举个例子 lis = [1,6,1, 2, 3,3, 4, 5] for i in lis: lis.remove(i) print(lis) [6, 1, 2, 3, 3, ...