Await 和Async初步体验

Async函数的介绍:

async 函数是什么?一句话,它就是 Generator 函数的语法糖。使用 关键字 async 来表示,在函数内部使用 await 来表示异步。

Promise写法

在我自己最早期的项目里面,数据请求是采用Promise编写的:

// 首页收银员登录
export function cashierLogin(data = '') {
   return new Promise((resolve, reject) => {
     const url = config.chain_api_url+"act=login&op=cashier_login";
     xFetch(url, 'post', data).then((e) => {
       resolve(e);
     }, (error) => {
       reject(error);
     })
   })
}

当处理逻辑简单的时候,只需要一次promise即可完成,但是在逻辑复杂的情况下 then().then().then().,这种代码写多了,代码量也没减多少,看起来也不是很舒服。

Generator语法

Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。

形式上,Generator 函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式。

调用 Generator 函数后,该函数并不执行,返回的也不是函数运行结果,而是一个指向内部状态的指针对象。

下一步,必须调用遍历器对象的next方法,使得指针移向下一个状态。也就是说,每次调用next方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield表达式(或return语句)为止。换言之,Generator 函数是分段执行的,yield表达式是暂停执行的标记,而next方法可以恢复执行。

   *showList(action, { select, call, put }) {
      const e = yield call(getTraficMessage);
      if(e.code == 200){
        yield put({type:'save_data',orderList:e.datas});
        if(action.first && e.datas!=''){
          const b = yield call(getTraficDetails,{stockflow_id:e.datas[0].stockflow_id});
          if(b.code == 200){
            yield put({type:'save_data',goods:b.datas.list})
          }
        }
      }

Async/await语法

想较于 Generator,Async 函数的改进在于下面四点:

  • 内置执行器。Generator 函数的执行必须依靠执行器,而 Aysnc 函数自带执行器,调用方式跟普通函数的调用一样
  • 更好的语义。async 和 await 相较于 * 和 yield 更加语义化
  • 更广的适用性。co 模块约定,yield 命令后面只能是 Thunk 函数或 Promise对象。而 async 函数的 await 命令后面则可以是 Promise 或者 原始类型的值(Number,string,boolean,但这时等同于同步操作)
  • 返回值是 Promise。async 函数返回值是 Promise 对象,比 Generator 函数返回的 Iterator 对象方便,可以直接使用 then() 方法进行调用

基本用法

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', 50);

上面代码指定 50 毫秒以后,输出hello world。

语法比较

假设一个业务,分多个步骤完成,每个步骤都是异步的,而且依赖于上一个步骤的结果。我们仍然用 setTimeout 来模拟异步操作:

/**
 * 传入参数 n,表示这个函数执行的时间(毫秒)
 * 执行的结果是 n + 200,这个值将用于下一步骤
 */
function takeLongTime(n) {
    return new Promise(resolve => {
        setTimeout(() => resolve(n + 200), n);
    });
}

function step1(n) {
    console.log(`step1 with ${n}`);
    return takeLongTime(n);
}

function step2(n) {
    console.log(`step2 with ${n}`);
    return takeLongTime(n);
}

function step3(n) {
    console.log(`step3 with ${n}`);
    return takeLongTime(n);
}

Promise

function doIt() {
    console.time("doIt");
    const time1 = 300;
    step1(time1)
        .then(time2 => step2(time2))
        .then(time3 => step3(time3))
        .then(result => {
            console.log(`result is ${result}`);
            console.timeEnd("doIt");
        });
}

doIt();

// c:\var\test>node --harmony_async_await .
// step1 with 300
// step2 with 500
// step3 with 700
// result is 900
// doIt: 1507.251ms

async

async function doIt() {
    console.time("doIt");
    const time1 = 300;
    const time2 = await step1(time1);
    const time3 = await step2(time2);
    const result = await step3(time3);
    console.log(`result is ${result}`);
    console.timeEnd("doIt");
}

doIt();

采用async写出来的代码,语义更加明显,而且看起来就像是同步代码一样。

猜你喜欢

转载自blog.csdn.net/xjl271314/article/details/79552634
今日推荐