天天看點

async 異步變同步ES6 async函數

ES6 async函數

目錄

  • ES6 async函數
    • 基本用法
    • async的特點
    • 使用注意點
    • 錯誤處理
    • 三種方法寫異步
async 異步變同步ES6 async函數

基本用法

ES2017 标準引入了 async 函數,使得異步操作變得更加友善

async函數是什麼?一句話,它就是Generator函數的文法糖

async 函數寫法

// 函數聲明
async function foo() {};

// 函數表達式
const foo = async function () {};

// 對象的方法
let obj = { async foo() {} };
obj.foo().then(...)

// Class 的方法
class Storage {
  constructor() {
    this.cachePromise = caches.open('avatars');
  }

  async getAvatar(name) {
    const cache = await this.cachePromise;
    return cache.match(`/avatars/${name}.jpg`);
  }
}

const storage = new Storage();
storage.getAvatar('jake').then(…);

// 箭頭函數
const foo = async () => {};
           

回到頂部 目錄

讀取兩個檔案:

const fs = require('fs');

const readFile = function (fileName) {
    return new Promise(function (resolve, reject) {
        fs.readFile(fileName, function (error, data) {
            if (error) return reject(error);
            resolve(data);
        });
    });
};

// Generator 函數寫法
const gen = function* () {
    const f1 = yield readFile('aa');
    const f2 = yield readFile('bb');
    console.log(f1.toString());
    console.log(f2.toString());
};

// async 函數寫法
const asyncFile = async function () {
  const f1 = await readFile('aa');
  const f2 = await readFile('bb');
  console.log(f1.toString());
  console.log(f2.toString());
};
           

分析async函數實作過程:

  1. 通過async關鍵字,表明該函數體内部是異步操作
  2. 調用該函數,遇到await就去任務隊列中執行異步操作,等到異步操作完成,在執行函數體後面的語句
  3. 傳回Promise對象
  4. 任何await語句後面的Promise對象變為reject狀态,那麼整個async函數都會中斷執行

回到頂部 目錄

async的特點

  1. 不需要像Generator去調用next()方法
  2. async傳回的總是Promise對象,可以用then方法進行下一步操作
  3. async取代Generator函數的星号*,await取代Generator函數的yield
  4. co子產品約定,yield指令後面隻能是 Thunk 函數或 Promise 對象,而async函數的await指令後面,可以是 Promise 對象和原始類型的值(數值、字元串和布爾值,但這時會自動轉成立即 resolved 的 Promise 對象)

使用注意點

  1. await指令後面的Promise對象,運作結果可能是rejected,是以最好把await指令放在try…catch代碼塊中
  2. 多個await指令後面的異步操作,如果不存在繼發關系,最好讓它們同時觸發
  3. await指令隻能用在async函數之中,如果用在普通函數,就會報錯
  4. async 函數可以保留運作堆棧

錯誤處理

async function myFunction() {
  try {
    await errfn();
  } catch (err) {
    console.log(err);
  }
}

// 另一種寫法
async function myFunction() {
  await errfn()
  .catch(function (err) {
    console.log(err);
  });
}
           

回到頂部 目錄

三種方法寫異步

var p = (val, isReject) =>{
    return new Promise((res,rej) =>{
        if(isReject){
            setTimeout(rej, 1000, val);
        }else{
            setTimeout(res, 1000, val);
        }
    })
}

// Promise對象方法
var p2 = new Promise((res, rej) => {
    p('one', false).then().then(val =>{
        console.log(val)
    })
})


// Generator 函數
var genP = function* (){
    yield p('two', false);
};
var gp = genP();
gp.next().value.then(val => {
    console.log(val)
});


// async 函數
var asyncP = async function(){
    var ap = await p('three', false);
    return ap;
}
asyncP().then(val =>{
    console.log(val)
})
           

回到頂部 目錄

繼續閱讀