async 和await

  1. await后面接一个会return new promise的函数并执行它
  2. await只能放在async函数里
  • 使用async和await获取成功的结果
function 摇色子(){
    return new Promise((resolve, reject)=>{
        let sino = parseInt(Math.random() * 6 +1)
        setTimeout(()=>{
            resolve(sino)
        },3000)
    })
}
async function test(){
    let n =await 摇色子()
    console.log(n)
}
test()

上面这段代码async中使await 摇色子()先执行,等到三秒后执行完再把得到的结果赋值给左边的n,也就是说test函数需要三秒钟才执行完成,所以test函数是异步的,因此前面必须写async

  • 获取失败的结果
function 摇色子(猜测){
    return new Promise((resolve, reject)=>{
        let sino = parseInt(Math.random() * 6 +1)
        if(sino > 3){
            if(猜测 === '大'){
                resolve(sino)
            }else{
                reject(sino)
            }
        }else{
            if(猜测 === '大'){
                reject(sino)
            }else{
                resolve(sino)
            }
        }
        setTimeout(()=>{
            resolve(sino)
        },300)
    })
}
async function test(){
    try{
        //把await及获取它的值的操作放在try里
        let n =await 摇色子('大')
        console.log('赢了' + n)
    }catch(error){
      //失败的操作放在catch里
        console.log('输了' + error)
    }
}
test()

把await和成功后的操作放到try里,失败的放在catch

  • 为什么要用await
    为了使我们的异步代码,更像同步的代码

  • 有多个promise,怎么拿到所有的promise都结束后的结果
    比如有两个色子,我想得到这两个色子的点数

  1. 使用promise
function 摇色子(猜测){
    return new Promise((resolve, reject)=>{
        let sino = parseInt(Math.random() * 6 +1)
        if(sino > 3){
            if(猜测 === '大'){
                resolve(sino)
            }else{
                console.log('error')
                reject(sino)
            }
        }else{
            if(猜测 === '大'){
                console.log('error')
                reject(sino)
            }else{
                resolve(sino)
            }
        }
        setTimeout(()=>{
            resolve(sino)
        },300)
    })
}
Promise.all([摇色子('大'),摇色子('大')]).then((x)=>{console.log(x)},(y)=>{console.log(y)})

promise.all里面跟一个数组,数组的每一项是一个返回promise的函数调用,then的第一个参数是所有的promise都成功后调用,拿到所有promise的结果是一个数组;第二个参数拿到的是第一个失败的值

  1. 使用await
    await是直接获取多个promise的结果的,因为Promise.all()返回的也是一个promise所以如果要使用await拿到多个promise的值,可以直接await Promise.all()
async function test(){
    try{
        let n = await Promise.all([摇色子('大'),摇色子('大')])
        console.log(n)
    }catch(error){
        console.log(error)
    }
}
test()
  • async函数会返回一个promise,并且Promise对象的状态值是resolved(成功的)
  1. 如果你没有在async函数中写return,那么Promise对象resolve的值就是是undefined

         2.如果你写了return,那么return的值就会作为你成功的时候传入的值

await 等到之后,做了一件什么事情?
那么右侧表达式的结果,就是await要等的东西。
等到之后,对于await来说,分2个情况

  • 不是promise对象
  • 是promise对象

如果不是 promise , await会阻塞后面的代码,先执行async外面的同步代码,同步代码执行完,再回到async内部,把这个非promise的东西,作为 await表达式的结果。
如果它等到的是一个 promise 对象,await 也会暂停async后面的代码,先执行async外面的同步代码,等着 Promise 对象 fulfilled,然后把 resolve 的参数作为 await 表达式的运算结果。

也可以理解为:await 操作符用于等待一个Promise 对象,并且返回 Promise 对象的处理结果(成功把resolve 函数参数作为await 表达式的值),如果等待的不是 Promise 对象,则用 Promise.resolve(xx) 转化

  • 如果asycn里的代码都是同步的,那么这个函数被调用就会同步执行
async function fn(){
  console.log('a')
}
fn()
console.log('b')
//a
//b
  • 如果在await后面接的这个promsie都是同步的,后面的promise会同步执行,但是拿到这个值还是得等待(特别注意:如果promise没有一个成功的值传入,对await来说就算是失败了,下面的代码就不会执行),所以不管await后面的代码是同步还是异步,await总是需要时间,从右向左执行,先执行右侧的代码,执行完后,发现有await关键字,于是让出线程,阻塞代码
function fn(){
    return new Promise(resolve=>{
        console.log(1)
    })
}
async function f1(){
    await fn()
    console.log(2)
}
f1()
console.log(3)
//1
//3

这个代码因为fn是属于同步的,所以先打印出1,然后是3,但是因为没有resolve结果,所以await拿不到值,因此不会打印2

function fn(){
    return new Promise(resolve=>{
        console.log(1)
        resolve()
    })
}
async function f1(){
    await fn()
    console.log(2)
}
f1()
console.log(3)
//1
//3
//2

这个代码与前面相比多了个resolve说明promise成功了,所以await能拿到结果,因此就是1 3 2

下面来看一个例子:

    let name = '';
    function change() {
      setTimeout(() => {
        return 'hello world';
      }, 2000);
    }
    async function test() {
      name = await change();
      console.log(name, 'test');
    }
    test();
    console.log('1111');
    
    // 1111
    // undefined "test"

 我们来分析一下代码执行的过程:

1.执行test()函数,在函数内部,name= await change();从右往左执行,先执行change()函数;change()函数内部是一个setTimeout()函数,放入异步事件队列中。

2.遇到awiat,阻塞后面的代码,跳出test()函数,执行外面的同步代码,打印‘1111’。

3.执行完test()外面的同步代码,再次回到test()函数中,这时setTimeout()还是异步队列中,所以change函数并没有return 任何值,所以这时await等待的结果是undefined,赋值给name,所以这时候打印的是undefined  'test'。

4.所有的同步函数执行完之后,这时setTimeout函数回到主线程,执行完成 return hello world。

若代码稍微改动一下:

    let name = '';
    function change() {
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve('hello world');
        }, 2000);
      });
    }
    async function test() {
      name = await change();
      console.log(name, 'test');
    }
    test();
    console.log('1111');

    // 1111
    // hello world test

 这时由于 await会堵塞后面的代码,直到等到promise的resolve的值,所以会打印 hello world



本文参考:https://www.jianshu.com/p/b4fd76c61dc9

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值