唯品秀前端博客
当前位置: 前端开发 > JavaScript > 你是否有了解Promise、Async and await

你是否有了解Promise、Async and await

2018-07-15 分类:JavaScript 作者:管理员 阅读(1545)

也许看到这些单词你第一反应就是“异步”,但你是否真的能好好使用它呢?

早在以前,我们都是通过回调的方式解决异步操作问题,就是运行一个函数,将另一个函数作为参数传进要执行的函数里,如下:

1
2
3
4
5
6
7
8
9
function f1(callback) {  
    setTimeout(function () {
       callback();  
    }, 2000);
}
var f2 = function(){
    console.log('回调')
}
f1(f2)

采用这种方式,我们把同步操作变成了异步操作,f1不会堵塞程序运行,相当于先执行程序的主要逻辑,将耗时的操作推迟执行。

回调函数是异步编程最基本的方法,其优点是简单、容易理解和部署,缺点是不利于代码的阅读和维护,各个部分之间高度耦合(Coupling),流程会很混乱,而且每个任务只能指定一个回调函数。

Promise

Promise最大的好处是在异步执行的流程中,把执行代码和处理结果的代码清晰地分离了,你可以在需要的时候自主的给出成功或失败,而返回的依然是一个promise对象,你可以继续通过then方式嵌套,then方法里面接收一个函数,函数的参数就是上个promise的return返回结果如下:

1
2
3
4
5
6
7
8
9
10
var p1 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 500, 'P1');
});
var p2 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 600, 'P2');
});
// 同时执行p1和p2,并在它们都完成后执行then:
Promise.all([p1, p2]).then(function (results) {
    console.log(results); // 获得一个Array: ['P1', 'P2']
});

Async and await

async 函数算是一个语法糖,使异步函数、回调函数在语法上看上去更像同步函数。Async和promise息息相关,其实它的核心还是promise,不同的是Async解决了promise的层层嵌套问题,并且很好的阻断了当代码发生异常时候阻断代码执行,async 返回一个Promise,因此这个函数可以通过then添加回调函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  function timeout(ms) {
    return new Promise((resolve) => {
      setTimeout(resolve, ms);
    });
  }
  function timeout1(ms) {
    return new Promise((resolve) => {
      setTimeout(resolve, ms);
    });
  }
  async function fn() {
    await timeout(1000);
    console.log(111)
    await timeout1(3000);//等待timeout函数执行完毕
    console.log(123321)//等待timeout1执行完毕
    return await('执行了!');
  }
 /*注:当一个 async 函数中有多个await时,这些 await是继发执行的,
   只有当前一个await后面的方法执行完毕后,才会执行下一个*/

  fn().then(res => {
    console.log(res)
  }).catch((err) => {
    console.log(err)
  })

await 命令

可以看到,在 async 函数中,出现了一个陌生的关键字await——这个关键字只能够在 async 函数中使用,否则将会报错,它的意思是紧跟在其后面的表达式需要被等待执行结果,同时值得注意的是,你必须将await等待的结果通过return出去,在fn().then里才能去接收到结果,否则会是undefined,这个同promise是一致的。

await命令后面可以是Promise也可以是普通数据类型,但如果是普通数据类型的话,会自动转换成状态为resolve的Promise,如果await后面的Promise状态转变成了reject,那么整个 async 函数都会停止执行,并且抛出相应的错误。即使这里没有return,也一样可以传入错误回调的参数,所以当一个 async 函数中有多个 await命令时,如果不想因为一个出错而导致其与的都无法执行,应将await放在try...catch语句中执行。

1
2
3
4
5
6
7
8
9
async function testAwait () {
    try { //监听下面方法有可能会抛出错误
        await func1()
        await func2()
        await func3()
    } catch (error) {
        console.log(error)
    }
}

上述说到,当一个 async 函数中有多个await时,这些 await是继发执行的,只有当前一个await后面的方法执行完毕后,才会执行下一个,如果我们前后的方法由依赖关系,继发执行是没有问题的,但是如果并没有任何关系的话,这样就会很耗时,所以需要让这些await命令同时执行,也就是并发执行。

1
2
3
4
5
6
7
8
// 方法 1
let [res1, res2] = await Promise.all([func1(), func2()])

// 方法 2
let func1Promise = func1()
let func2Promise = func2()
let res1 = await func1Promise
let res2 = await func2Promise

「两年博客,如果觉得我的文章对您有用,请帮助本站成长」

赞(3) 打赏

谢谢你请我吃鸡腿*^_^*

支付宝
微信
3

谢谢你请我吃鸡腿*^_^*

支付宝
微信
标签:

上一篇:

下一篇:

你可能感兴趣

共有 0 条评论 - 你是否有了解Promise、Async and await

博客简介

唯品秀博客: weipxiu.com,一个关注Web前端开发技术、关注用户体验、坚持更多原创实战教程的个人网站,愿景:成为宇宙中最具有代表性的前端博客,期待您的参与 

精彩评论

友情链接

他们同样是一群网虫,却不是每天泡在网上游走在淘宝和网游之间、刷着本来就快要透支的信用卡。他们或许没有踏出国门一步,但同学却不局限在一国一校,而是遍及全球!申请交换友链

站点统计

  • 文章总数: 231 篇
  • 草稿数目: 0 篇
  • 分类数目: 14 个
  • 独立页面: 6 个
  • 评论总数: 848 条
  • 链接总数: 12 个
  • 标签总数: 416 个
  • 建站时间: 980 天
  • 注册用户: 1856 人
  • 访问总量: 8653120 次
  • 最近更新: 2019年8月22日
服务热线:
 173xxxx7240

 QQ在线交流

 旺旺在线