es6中的async&await异步调用方法

基本用法

async函数

  • async定义的函数返回一个Promise对象,可以使用then方法添加回调函数。

      async function timeout() {
          return 'hello world'
      }
      console.log(timeout());
      console.log('虽然在后面,但是我先执行');
    

  • 它和promise一样,有异步回掉功能

      async function timeout() {
          return 'hello world'
      }
      timeout().then(result => {
          console.log(result);
      })
      console.log('虽然在后面,但是我先执行');
    

  • async原理:如果async成功返回一个promise对象,实际会调用Promise.resolve()返回,否则会调用Promise.reject()

      async function timeout(flag) {
          if (flag) {
              return 'hello world'
          } else {
              throw 'my god, failure'
          }
      }
      console.log(timeout(true))  // 调用Promise.resolve() 返回promise 对象。
      console.log(timeout(false)); // 调用Promise.reject() 返回promise 对象。
    

await

当函数执行时,一旦遇到await(后面定义的也是一个promise对象)就会先返回,等异步操作完成,再执行后面的语句。

await只能出现在async函数内部,等待async函数返回或执行promise,

// 2s 之后返回双倍的值
function doubleAfter2seconds(num) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(2 * num)
        }, 2000);
    } )
}

async function testResult() {
    let result = await doubleAfter2seconds(30);
    console.log(result);
}

testResult(); //2s后输出60

代码执行过程:

  1. 调用testResult()函数,遇到await,开始等待(后面的promise执行完毕)
  2. 执行await后的doubleAfter2seconds(30),返回promise开始执行,2s后执行完毕,值为60并返回
  3. await拿到60,赋值给result,等待结束,代码继续运行,执行console

这里如果计算多个值,可以像写同步代码那样,避免回掉地狱

async function testResult() {
    let first = await doubleAfter2seconds(30);
    let second = await doubleAfter2seconds(50);
    let third = await doubleAfter2seconds(30);
    console.log(first + second + third);
}

demo

  • 获取股票报价的函数(可以用.then处理async函数)
async function getStockPriceByName(name) {
  const symbol = await getStockSymbol(name);
  const stockPrice = await getStockPrice(symbol);
  return stockPrice;
}

getStockPriceByName('goog').then(function (result) {
  console.log(result);
});
  • 在api中,把结果return 出去
export async function getRetailUnitPrice () {
const reqBody = await get('/race/spot/racespot/enter/dayahead')
return reqBody
}

注意点

  • async函数返回的promise对象,必须等到内部所有await命令后面的对象执行完,才会执行then
  • 当async返回一个常量,返回Promise.resolve(常量)自动构建promise返回值
  • 当async函数没有返回值的时候,返回Promise.resolve(undefiend)自动构建promise返回值
async function getTitle(url) {
  let response = await fetch(url);
  let html = await response.text();
  return html.match(/<title>([\s\S]+)<\/title>/i)[1];
}
getTitle('https://tc39.github.io/ecma262/').then(console.log)
// "ECMAScript 2017 Language Specification"

与promise相比

优点:处理.then链,不必把回掉嵌套在.then中,只要await即可

function sing() {
        return new Promise(function(resolve, reject) {
            setTimeout(function() {
                resolve(`来一首好听的歌吧~~~`);
            }, 1000);
        });
    }
    async function demo() {
        try {
            const v = await say(); 
            const s = await sing(); 
            console.log(v); // 输出:hello, joel。今年我 26 岁
            console.log(s) // 来一首好听的歌吧~~~
        } catch (e) {
            console.log(e)
        }
    }
    demo();

如果使用原来的Promise 就是把回调放在then()中。