陌上寒

陌上寒个人博客

javascript异步实战

《javascript异步实战》
今天的主角是async await
之前说过async 就是 Generator 的语法糖

Generator简单回顾

看一段伪代码(纯展示逻辑,跑不起来的)

function* getData() {
  yield loadData1()//“这个执行成功后执行it.next(),启动下一个yield,没有yield就执行return,没有return 就是return undefined”
  yield loadData2()//“这个执行成功后执行it.next(),启动下一个yield,没有yield就执行return,没有return 就是return undefined”
  yield loadData3()//“这个执行成功后执行it.next(),启动下一个yield,没有yield就执行return,没有return 就是return undefined”
}
const it = getData()
it.next()//“启动生成器”

执行的逻辑看上面的代码注释,真正处理异步的时候,我相信很有有人用Generator来处理,至少我不会,太麻烦了
这时候async来了,它的出现大大简化了Generator的使用

async简单介绍

上面的伪代码,用async来实现

async function getData() {
  await loadData1()
  await loadData2()
  await loadData3()
}
getData()

async就像是Generator中的“*”,await就相当于Generator中的yield,同样的await只能在使用了async的函数内使用

关于async的返回

一个小栗子

  async function doSth() {
    const GJ = '郭靖在发呆'
  } 
  console.log(doSth());//=>Promise {<resolved>: undefined}

async 自动把函数转换为 Promise,返回的是一个Promise对象
关于async的介绍的文章,多如牛毛,我么不再赘述,进入主题

异步实战

还是那个需求

现在有接口1,接口2,接口3
按顺序输出接口1,接口2,接口3的值

我们上一次分别用了回调函数嵌套,原生的Promise,以及Generator来实现的这个功能
ajax是使用jquery

在写法上还是有些“hello world”,因为内容太理论,我们下面采用axios+async来实现
上面的需求可以这么理解,先调用接口一,接口二的执行依赖于接口一的返回,接口三的执行依赖于接口二的返回
所以,接口一,接口二,接口三,需要同步的按顺序执行,因为现在ajax请求基本都是通过异步来处理的
众所周知,axios返回的一个Promise对象,下面的栗子依赖于这一特性
为了简化demo的流程,方便大家实战操作,我没有搭建webpack或者babel环境,
就是新建了一个html页面,在浏览器控制台查看效果
因为兼容问题,建议使用Chrome浏览器进行操作
首先

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

js部分,easy-mock上面有三个接口,接口一和接口二的返回值很简单,接口三返回值是长度在10-20之间的数组,
以保证接口三的返回时间要长一些,以体现异步效果

// 一个函数p11,返回一个axios,Promise对象
function p11() {
    return axios('https://easy-mock.com/mock/5b0525349ae34e7a89352191/example/promise1')
        .then(({
        data
    }) => {
        if (data.data.name) {
            return data.data.name
        }
    })
}
// 一个函数p22,返回一个axios,Promise对象
function p22() {
  return axios('https://easy-mock.com/mock/5b0525349ae34e7a89352191/example/promise2')
    .then(({
      data
    }) => {
      if (data.data.name) {
        return data.data.name
      }
    })
}
// 一个函数p33,返回一个axios,Promise对象
function p33() {
  return axios('https://easy-mock.com/mock/5b0525349ae34e7a89352191/example/mock')
    .then(({
      data
    }) => {
      if (data.success) {
        return data.data.projects
      }
    })
}

三个请求已经封装完毕,函数没有cnsole.log
作为比较,也作为复习,我们看下Promie的实现

p11()
  .then(res1 => {
    console.log(res1);
    return p22()
  })
  .then(res2 => {
    console.log(res2);
    return p33()
  }).then(res3 => {
    console.log(res3);
    return res3
  })

输出
《javascript异步实战》
对此没什么可以赘述的

async 处理异步

再我们看下async

async function asyncFUn() {
  const RES1 = await p11();
  console.log(RES1);
  const RES2 = await p22();
  console.log(RES2);
  const RES3 = await p33();
  console.log(RES3);
  return RES3;
}
asyncFUn()

await的存在 使异步变成了同步
在处理异步的时候,await后面要根的是一个返回Promise的函数
就像上面的p11,p22,p33,函数都是返回一个axios(axios返回一个Promise对象),如果不是就用Promise包装一下
否则会出现这样的结果

 <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
function loadData1() {
  $.ajax({
    url: "https://easy-mock.com/mock/5b0525349ae34e7a89352191/example/promise1",
    success: ({
      data,
      success
    }) => {
      if (success) {
        console.log(`接口一返回:${data.name}`);
        return data.name
      }
    }
  });
}

function loadData2() {
  $.ajax({
    url: "https://easy-mock.com/mock/5b0525349ae34e7a89352191/example/promise2",
    success: ({
      data
    }) => {
      console.log(`接口二返回:${data.name}`);
      return data.name
    }
  });
}

function loadData3() {
  $.ajax({
    url: "https://easy-mock.com/mock/5b0525349ae34e7a89352191/example/mock",
    success: ({
      data,
      success
    }) => {
      if (success) {
        console.log('接口三返回', data.projects);
        return data.projects
      }
    }
  });
}
async function asyncFUn1() {
  const RES1 = await loadData1();
  console.log(RES1);//=>undefined
  const RES2 = await loadData2();
  console.log(RES2);//=>undefined
  const RES3 = await loadData3();
  console.log(RES3);//=>undefined
  return RES3;
}
asyncFUn1()

输出
《javascript异步实战》
这时候就需要用Promise进行包装。类似于这样

function loadData1() {
    return new Promise((resolve, reject) => {
        $.ajax({
            url: "https://easy-mock.com/mock/5b0525349ae34e7a89352191/example/promise1",
            success: ({
                data,
                success
            }) => {
                if (success) {
                    console.log(`接口一返回:${data.name}`);
                    resolve(data.name)
                }
            }
        });
    })
}
//后面省略

如果不是异步,那就没有必要通过await来处理了,当然await后面也支持非异步,可以自行实践

async 处理报错

看到了,async中没有then catch,怎么处理报错信息呢?
天无绝人之路,使用try catch

async function asyncFUn() {
  const RES1 = await p11();
  console.log(RES1);
  const RES2 = await p22();
  console.log(RES2);
  const RES3 = await p33();
  console.log(RES3);
  return RES3;
}
try {
  asyncFUn()
} catch (error) {
  console.log(error);
}

好,关于async await 就介绍到这里
END

发表评论

电子邮件地址不会被公开。 必填项已用*标注