async/await 异步

async/await 是一个用同步的思维来解决异步问题的方案。

async 函数就是 Generator 函数的语法糖。

async 函数的优点

async写在function前面,该函数返回值是一个promise,可以直接使用then方法。

async function test() {
    return "test";
}

test().then(function(v) {
    console.log(v);
});  //“test”

await只能在async函数中使用。

async function test() {
    return "test";
}

var v = await test();
console.log(v);  //“test”

await不能工作在顶级作用域,需要将await代码包裹在一个async函数中

await接受thenables

就像promise.then,await也允许使用thenable对象(那些具有可调用的then方法的对象)。同样,第三方对象可能不是一个promise,但是promise的兼容性表示,如果它支持.then方法,那么它就能用于await。

例如,这里await接受了new Thenable(1)

class Test {
    constructor(str) {
        this.str= str;
    }
    then(resolve, reject) {
        setTimeout(() => {
            resolve(this.str);
        }, 1000);
   }
}
async function fun() {
    let result = await new Test("abc");
    console.log(result);
}
fun();

如果await得到了一个带有then方法的非promise对象,它将会调用提供原生函数resolve、reject作为参数的方法,然后await一直等待,直到他们其中的一个被调用。

async方法
一个class方法同样能够使用async,只需要将async放在它之前就可以
就像这样:

class Waiter {
   async wait () {
       return await Promise.resolve(1)
   }
}
new Waiter().wait().then(alert) // 1

这里的意思是一样的:它确保了返回值是一个promise,支持await

async、await串行并行处理

串行:等待前面一个await执行后接着执行下一个await,以此类推

async function test(str) {
     return await new Promise((resolve, reject) => {
         setTimeout(() => {
            resolve(str);
         }, 1000);
     })
 }
 
 var fun = async () => { //串行执行
     console.time('fun');
     console.log(await test('async 1'));
     console.log(await test('async 2'));
     console.log(await test('async 3'));
     console.timeEnd('fun');
}

fun();

可以看到两个await串行执行的总耗时为两千多毫秒。

并行:将多个promise直接发起请求(先执行async所在函数),然后再进行await操作。

async function test(str) {
    return await new Promise((resolve, reject) => {
         setTimeout(() => {
            resolve(str);
        }, 1000);
     })
 }
 var fun1 = async () => { //并行执行
     console.time('fun');
     const t1 = test('async 1');
     const t2 = test('async 2');
     const t3 = test('async 3');

     //直接打印
     console.log(await t1);
     console.log(await t2);
     console.log(await t3);

     console.timeEnd('fun');
}

var fun2 = async () => { //串行执行
     console.time('fun2');

     const t1 = test('async 1');
     const t2 = test('async 2');
     const t3 = test('async 3');

     const t = [t1, t2, t3];
     console.log(await Promise.all(t));

     console.timeEnd('fun2');
}

fun1();
fun2();


fun1与fun2写法效果基本无异

通过打印我们可以看到相对于串行执行,效率提升了一倍。在并行请求中先执行async的异步操作再await它的结果,把多个串行请求改为并行可以将代码执行得更快,效率更高。

错误处理

可以使用try-catch语句捕获错误,就像在正常抛出中处理异常一样。

如果我们不使用try-catch,然后async函数的调用产生的promise变成reject状态的话,我们可以添加.catch去处理它:

如果我们忘记添加.catch,我们就会得到一个未被处理的promise错误(能够在控制台里看到它),这时我们可以通过使用一个全局的事件处理器去捕获错误。

async function myFun() {
  try {
    await fun();
  } catch (err) {
    console.log(err);
  }
}

// 另一种写法
async function myFun() {
  await fun().catch(function (err){
    console.log(err);
  });
}

总结

放在一个函数前的async有两个作用:

1)使函数总是返回一个promise

2)允许在这其中使用await

有了async/await,很少需要写promise.then/catch,但是Promise.all没有替代方式,它能够同时等待很多任务。

async/await对比Promise优点:

1) 真正地用同步的方式写异步代码

2) 不用写then及其回调函数,减少代码行数,也避免了代码嵌套

3) 所有异步调用可以写在同一个代码块中,无需定义多余的中间变量

4) async函数会隐式地返回一个Promise,因此可以直接return变量,无需使用Promise.resolve进行转换

猜你喜欢

转载自blog.csdn.net/weixin_42441117/article/details/82427173