• 主页
  • 归档
  • 分类
  • 照片墙
所有文章 友情链接 关于我

  • 主页
  • 归档
  • 分类
  • 照片墙
  1. 1. async的作用
  2. 2. await的作用
  3. 3. setTimeout与Promise
  4. 4. 综合运用

Promise(3)-async与await

2018-12-06 15:29:07
总字数 923
预计阅读时间 3 分钟

async的作用

首先async关键字是用来修饰函数的
带有async的函数, 调用的返回值必定是一个Promise对象

  1. 如果本身返回的就是Promise对象, 则不会做任何处理
  2. 如果本身返回的不是Promise对象, 则会用Promise.resolve包装后再返回
1
2
3
4
5
6
7
8
9
async function test1() {
return '123'
}
const p1 = test1()
// 等价于如下写法
function test2() {
return '123'
}
const p2 = Promise.resolve(test2())

await的作用

await是用来修饰表达式的
表示等待这个表达式的执行结果
限制就是必须使用在async函数当中, 否则就会报错
await

表达式的结果可以是Promise对象, 也可以不是

  • 不是promise对象 : await会阻塞后面的代码,先执行await所在的async函数调用之后的同步代码,同步代码执行完,再回到async内部,把这个非promise的东西,作为 await表达式的结果
    例如

    1
    2
    3
    4
    5
    6
    7
    8
    console.log(1);
    (async function(){
    /* 存在await导致该函数异步执行, 所以会先输出之后的3 */
    console.log(await 4); //阻塞之后的2
    console.log(2);
    })();
    console.log(3);
    /* output: 1 3 4 2 */

    正因为await会阻塞之后的代码, 所以才必须放在async函数当中

  • 是promise对象 : await 也会阻塞async后面的代码,先执行async外面的同步代码,等着 Promise 对象 fulfilled,然后把 resolve 的参数作为 await 表达式的运算结果。
    例如

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    async function test() {
    console.log(4)
    return 1
    }

    (async function(){
    // 因为test函数是async修饰的, 所以返回的是Promise对象
    console.log(await test())
    console.log(2)
    })()
    console.log(3)
    /* output: 4 3 1 2 */

setTimeout与Promise

Promise是一个micro task,我们的主线程是一个task。micro task会在task后面执行,然后才会接着执行下一个task。
而setTimeout的返回函数是一个新的task,所以这里Promise的执行会先于新task执行

简单来说就是
setTimeout的队列与promise的队列不是同一个队列,执行的优先级低于promise


综合运用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
async function async1() {
console.log( 'async1 start' ) // (3)
await async2() // (4)
console.log( 'async1 end' ) // (5)
}

async function async2() {
console.log( 'async2' ) // (6)
}

console.log( 'script start' ) // (1)

setTimeout( function () {
console.log( 'setTimeout' ) // (2)
}, 0 )

async1()

new Promise( function ( resolve ) {
console.log( 'promise1' ) // (7)
resolve();
} ).then( function () {
console.log( 'promise2' ) // (8)
} )
console.log( 'script end' ) // (9)

执行过程分析:

  1. 开始是async1和async2两个函数定义, 但是没有调用, 所以先跳过, 首先执行的肯定是(1), 输出script start

  2. 然后是一个定时器, 那么此时会吧定时器的回调函数加入到任务队列当中

    此时的task队列 [ (2) ]

  3. 然后是async1的调用, 会先执行(3), 输出async1 start

  4. 执行到(4)时, 会阻塞之后的内容, 也就是(5), 并加入任务队列
    但是async2函数内部的内容不会阻塞, 还是同步执行, 执行(6), 输出async2

    此时的micro task队列 [ (5) ]

  5. 之后创建Promise对象, 构造方法传入的函数是立即执行的, 执行(7), 输出promise1

  6. resolve的执行加入到任务队列, 也就是(8)

    此时的micro task队列 [ (5) (8) ]

  7. 最后的(9)属于主线, 所以直接执行, 输出script end

  8. 主线执行完毕, 开始执行任务队列当中的内容, 首先会执行micro task队列的内容
    依次输出async1 end和promise2

  9. micro task队列出队执行完毕, 开始执行新的task队列(由setTimeout创建的)
    所以输出setTimeout

最终的输出结果是:

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

说明: 不同的js引擎的实现, async1 end和promise2的顺序可能有差别, 其他的顺序都是一样的

  • JavaScript
  • Promise
  • JavaScript

扫一扫,分享到微信

正则表达式重新入门(1)
持续集成-jenkins 
© 2024 夏夜梦星辰
鲁ICP备19028444号
Power By Hexo
  • 所有文章
  • 友情链接
  • 关于我
{{searchItem.query}}
标签: 分类:
  • maven
  • 持续集成
  • JMS
  • 线程
  • JavaScript
  • ECMAScript6
  • 单元测试
  • Promise
  • Web Worker
  • 函数
  • prototype
  • 模块化
  • 正则表达式
  • 数据库
  • MongoDB
  • 索引
  • 集群
  • 全文检索
  • flutter
  • dart
  • git
  • 版本控制
  • linux
  • shell
  • docker
  • nginx
  • jenkins
  • opencv
  • vim
  • react
  • react native
  • 前端
  • css
  • HTML5
  • Hexo
  • sass
  • Three.js
  • TypeScript
  • Vue
  • 组件化
  • base64
  • webpack
  • nodejs
  • gulp
  • TensorFlow
  • 机器学习
  • 算法
  • 动态规划
  • 数据结构
  • Java
  • JavaScript
  • MongoDB
  • flutter
  • Git
  • linux
  • react
  • 前端杂烩
  • 男生女生
  • 算法
  • 十年饮冰,难凉热血
  • †少女癌†
  • 猫与向日葵
  • coderfun
  • JENKINS
  • API管理后台
愿你最终能接纳每一面每一种的自己
独自活着便是团圆