一看就懂的async-await

async-await异步处理和使用

好不容易看完了Promise心想着可算是能用一下了,结果就看到了各种标题为:有了async-await以后promise还有必要学习吗?async await优于promise的几个特点。。。然后我就懵圈了,我的内心emmmmm。
原来,async-awaitpromisegenerator的语法糖,只是为了让我们书写代码更加流畅,增强代码的可读性,简而言之:async-await是建立在promise机制之上的,并不能取代promise

async-await基本使用

async函数返回一个Promise对象,可以使用then方法添加回调函数。
当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。

function timeout(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms)
  })
}

async function asyncPrint(value, ms) {
  await timeout(ms)
  console.log(value)
}

asyncPrint('hello world', 2000);
//hello world (2s后)

上面代码指定2000毫秒以后,输出hello world。同时函数asyncPrint()执行结果返回了一个promise对象。

async

async用来表示函数是异步的,定义的函数会返回一个promise对象,可以使用then方法添加回调函数,而async函数内部return语句返回的值,就会成为then方法回调函数的参数。针对上面的asyncPrint例子来看,如果我们直接使用then会发现什么都没有

function timeout(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms)
  })
}

async function asyncPrint(value, ms) {
  await timeout(ms)
  console.log(value)
}

asyncPrint('hello world', 2000).then((value)=>{console.log(value)})
//hello world (2s后)
//undefined

因为函数asyncPrint内部没有return语句返回值,那我们加上return试一下

function timeout(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms)
  })
}

async function asyncPrint(value, ms) {
  await timeout(ms)
  console.log(value)
  return 'done'
}

asyncPrint('hello world', 2000).then((value)=>{console.log(value)})
//hello world (2s后)
//done

其实就是相当于执行了Promise.resolve('done'),如果没有return就相当于Promise.resolve()

await

await后面可以跟任何JS表达式,虽然await可以跟很多类型的东西,但是最主要的意图是用来等待Promise对象的状态被resolved如果await的是promise对象会造成异步函数停止执行并等待promise解决,如果等到的是正常的表达式就立即执行,还是开头的那个例子,如果await的不是promise对象会怎么样

function timeout(ms) {
  setTimeout(()=>{}, ms)
}

async function asyncPrint(value, ms) {
  await timeout(ms)
  console.log(value)
}

asyncPrint('hello world', 2000);
//hello world (立即)

因为await后面不是promise对象了,也就不需要等待结果返回了,所以到这就直接往下执行了。
再来一个例子

function sleep(second) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('enough sleep~');
        }, second);
    })
}
function normalFunc() {
    console.log('normalFunc');
}
async function awaitDemo() {
    await normalFunc();
    console.log('something, ~~');
    let result = await sleep(2000);
    console.log(result);// 两秒之后会被打印出来
}
awaitDemo();
// normalFunc
// something, ~~
// ---2s后---
// enough sleep~

第一个await后面是一个正常表达式所以直接执行后继续往下执行,然后再遇到第二个await,这个await后面是一个异步操作,所以需要等待结果返回并执行后再继续往下执行,也就是过了2s以后再打印最后的值。

回调实例

举例说明,假设有三个请求需要发生,第三个请求是依赖第二个请求的解析,第二个请求是依赖第一个请求的解析
如果要用ES5实现就会有三个回调
如果用Promise就会至少有三个then
一个是横向代码很长,一个是纵向代码很长,如果用async-await来实现呢?

//我们仍然使用 setTimeout 来模拟异步请求
    function sleep(second, param) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(param);
            }, second);
        })
    }

    async function test() {
        let result1 = await sleep(1000, 'req01');
        console.log(result1)
        let result2 = await sleep(1000, 'req02' + result1);
        console.log(result2)
        let result3 = await sleep(1000, 'req03' + result2);
        console.log(result3)
    }

    test();
    //req01 --1s后--
    //req02req01 --2s后--
    //req03req02req01 --3s后--

难怪说async-awaitpromise的语法糖了,其实还是promise,只是代码阅读起来让你觉得它好像是一个同步请求,不用那么多回调或者then了。amazing!!!

小心并行处理

如果有多个await命令后面的异步操作之间不存在相互依赖的关系,那我们当然就不能使用上面实例中的方法来使用async-await了
例如有三个异步请求需要发送,但是相互之间没有关联,要做的其实就是当所有异步请求结束后清除界面上的loading,如果我们像上面那样使用当最后一个请求结束后清除loading,其实等待的时间就是三个请求时间之和:

function sleep(second) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('sth');
        }, second);
    })
}

async function clearLoad() {
    await sleep(1000);
    await sleep(1000);
    await sleep(1000);
    console.log('清除loading啦');
}

clearLoad();
// 清除loading啦 --3s后--

其实这里真正的需求是当最慢的那个请求发送结束了,就可以清除loading了,所以改良后是这样:

function sleep(second) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('sth');
        }, second);
    })
}

async function clearLoad() {
    let p1 = sleep(1000);
    let p2 = sleep(1000);
    let p3 = sleep(1000);
    await Promise.all([p1, p2, p3]);
    console.log('清除loading啦');
}

clearLoad();
// 清除loading啦 --1s后--

所以,以上可以得出:async-awaitpromise的语法糖,让我们书写代码更加流畅,增强代码的可读性,它是建立在promise机制之上的,并不能取代promise

猜你喜欢

转载自blog.csdn.net/weixin_43443341/article/details/86698580