唯品秀前端博客

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

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

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);
});
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: [undefined, '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); // 一定要执行resolve,否则await后面函数不往下执行
    });
  }
  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
本站所有文章、图片、资源等如无特殊说明或标注,均为来自互联网或者站长原创,版权归原作者所有;仅作为个人学习、研究以及欣赏!如若本站内容侵犯了原著者的合法权益,可联系我们进行处理,邮箱:343049466@qq.com
赞(4) 打赏
标签:

上一篇:

下一篇:

相关推荐

0 条评论关于"你是否有了解Promise、Async and await"

表情

最新评论

    暂无留言哦~~
谢谢你请我吃鸡腿*^_^*

支付宝扫一扫打赏

微信扫一扫打赏