Sunny-lucking/blog

将这段async/await代码翻译成Promise

Sunny-lucking opened this issue · 0 comments

如图,这道题,我轻而易举地说出了答案是2,3。原理的话我知道是封装成Promise,但要我翻译成Promise我还是很懵逼啊。 不得不学下怎么翻译。

不得不说,感谢这道题,让我进一步地深入了解async/await,感谢面试官

async/await 的基础使用及原理简介

async/await是es7推出的一套关于异步的终极解决方案,为什么要说他是终极解决方案呢?因为他实在是太好用了,而且写起来还非常的简单。

一:async/await基础语法

// 定义一个异步函数(假设他是一个异步函数)
getJSON(){
    return 'JSON'
}

// 在需要使用上面异步函数的函数前面,加上async声明,声明这是一个异步函数
async testAsync() {
  // 在异步函数前面加上await,函数执行就会等待用await声明的异步函数执行完毕之后,在往下执行
  await getJSON()
  
  ...剩下的代码
}

以上就是async/await最基本的用法。

还需要注意的一点就是使用async/await的时候,是无法捕获错误的,这个时候就要用到我们es5里面一个被大家遗忘了的try/catch,来进行错误的捕获:

async testAsync() {
  try {
     await getJSON()
  } catch(err) {
     console.log(err)
  }
  ...剩下的代码
}
注意:

1.async函数在声明形式上和普通函数没有区别,函数声明式,函数表达式,对象方法,class方法和箭头函数等都可以声明async函数。

2.任何一个await语句后面的 Promise 对象变为reject状态,那么整个async函数都会中断执行。

3.async函数返回的 Promise 对象必须等到内部所有await命令后面的 Promise 对象执行完,才会发生状态改变,除非遇到return语句或者抛出错误。也就是说,只有async函数内部的异步操作执行完,才会执行then方法指定的回调函数。

二:async/await

async这个单词大家应该都比较熟悉,他是英文单词‘异步’的简写,代表的意思也是异步。

async function testAsync() {
    return "hello async";
}

const result = testAsync();
console.log(result);

输出结果:

Promise{<resolved>: "hello async"}

可以看出async函数,返回的是一个Promise对象

await是英文单词‘等待’的意思,代表的意思也是等待,那他等的到底是个什么东西呢?还是一个Promise。

三、async/await和Promise直接的转化

async/await其实是基于Promise的。async函数其实是把Promise包装了一下。

下面是一个async/await的写法:

getConstant() {
   return 1
 }

 async getAsyncConstant() { 
  return 1
 }

 async getPromise() {
  return new Promise((resolved, rejected)=> {
    resolved(1)
  });
 }

 async test() {
  let a = 2
  let c = 1
  await getConstant();
  let d = 3
  await getPromise();
  let d = 4
  await getAsyncConstant();
  return 2
 }

上面的代码其实真正的在解析执行的时候是这样的:

function getConstant() {
   return 1;
}

function getAsyncConstant() {
  return Promise.resolve().then(function () {
   return 1;
  });
}

function getPromise() {
  return Promise.resolve().then(function () {
   return new Promise((resolved, rejected) => {
    resolved(1);
   });
  });
}

  test() {
    return Promise.resolve().then(function () {
       let a = 2;
       let c = 1;
       return getConstant();
     }).then(function () {
       let d = 3;
       return getPromise();
     }).then(function () {
       let d = 4;
       return getAsyncConstant();
     }).then(function () {
       return 2;
     });
 }

通过上面的代码可以看出async/await的本身还是基于Promise的。

因为await本身返回的也是一个Promise,它只是把await后面的代码放到了await返回的Promise的.then后面,以此来实现的。

因此回答题目

     function getJson(){
      return new Promise((reslove,reject) => {
        setTimeout(function(){
          console.log(2)
          reslove(2)
        },2000)
      })
     }
    async function testAsync() {
       await getJson()
       console.log(3)
    }

    testAsync()

自己封装一下,变成啥样?

function getJson(){
    return new Promise((resolve,rej)=>{
        setTimeout(function(){
            console.log(2)
            resolve(2)
          },2000)
    })
 }
function testAsync() {
    return Promise.resolve().then(()=>{
        return getJson()
    }).then(()=>{
        console.log(3)
    })
}

testAsync()

你封装对了吗?

多疑的你可能就要问了。要是我把getJson函数体题改成不是返回Promise呢?如下:

function getJson(){
  setTimeout(function(){
     console.log(2)
  },2000)
 }
  async function testAsync() {
       await getJson()
       console.log(3)
    }
  testAsync()

testAsync()

这样的话输出就是3,2了,但是我们刚刚的封装依旧没问题,如下所示

function getJson(){
    setTimeout(function(){
       console.log(2)
    },2000)
   }
  function testAsync() {
      return Promise.resolve().then(()=>{
          return getJson()
      }).then(()=>{
          console.log(3)
      })
  }
  
  testAsync()

因为return getJson()是在then里执行的,所以会返回promise。所以await等待的依旧是一个promise对象。

有点意思,有点意思。。。

但是还有点问题 ,用await的时候,我们平时都是用来接收异步执行后返回的数据啊,例如

// 这个是模拟简单的用Promise封装ajax
function getJson(){
    return new Promise((resolve,reject)=>{
        setTimeout(function(){
            resolve(99999)
        },3000)
    })
}
    async function testAsync() {
         let data = await getJson()
         console.log(1)
         console.log(data)
      }
  
  testAsync()

那,怎翻译过来呢??且看,

function getJson(){
    return new Promise((resolve,reject)=>{
        setTimeout(function(){
            resolve(99999)
        },3000)
    })
}
  function testAsync() {
        return Promise.resolve().then(()=>{
            return getJson()
        }).then((res)=>{
            let data = res
            console.log(1)
            console.log(data)
        })
         
      }
  
  testAsync()

是不是感觉so easy