理解ES7中的async/await

理解ES7中的async/awaitpromise

   優點是:就是解決多層異步回調的嵌套異步

 從字面上理解 async/await, async是 "異步"的含義,await能夠認爲是 async wait的簡寫,所以能夠理解 async 用於聲明一個function是異步的,而await用於等待一個異步方法執行完成返回的值(返回值能夠是一個Promise對象或普通返回的值)。
注意:await 只能出如今 async函數中。async

1-1 async的做用?
首先來理解async函數是怎麼處理返回值的,咱們之前寫代碼都是經過return語句返回咱們想要的值,可是async與return有什麼區別呢? 下面咱們看以下代碼:函數

async function testAsync() {
  return 'hello world';
}
const result = testAsync();
console.log(result);  // 打印出來看到 返回一個promise對象

如上代碼,咱們輸出的是一個Promise對象。所以 async返回的是一個Promise對象,所以咱們可使用 then()鏈來處理這個Promise對象。像以下代碼:優化

async function testAsync() {
  return 'hello world';
}
const result = testAsync();
result.then(v => {
  console.log(v);  // 輸出 hello world
});

可是若是 async函數沒有返回值的話,那麼就會返回 undefined; 以下代碼:spa

async function testAsync() {
  return;
}
const result = testAsync();
result.then(v => {
  console.log(v);  // 輸出 undefined
});

1-2 await的做用?
從語義上說,await是在等待一個async函數完成的,async函數返回的是一個Promise對象,await等待的是一個表達式,這個表達式的計算結果是Promise對象或其餘值。
async函數返回一個Promise對象,await做用是用於等待一個async函數的返回值。
await函數後面能夠接普通函數調用或直接量,請看以下代碼:code

function getSomething() {
  return 'something';
}

async function testAsync() {
  return Promise.resolve('hello');
}

async function test () {
  const v1 = await getSomething();
  const v2 = await testAsync();
  console.log(v1);  // something
  console.log(v2);  // hello
}
test();

注意:await 是等待async函數返回的Promise對象或其餘值,await是一個運算符,用於組成表達式, 若是等待的是一個Promise對象,await會阻塞後面的代碼(async調用不會形成堵塞,它內部全部的堵塞
都被封裝在一個Promise對象中異步執行),等待Promise對象的resolve,而後獲得resolve的值,做爲await表達式的運輸結果。對象

1-3 async/await 的一塊兒使用的做用及優點在哪?
咱們先不用 async/await, 來看看使用setTimeout模擬異步操做以下代碼:blog

var test = function(time) {
  return new Promise((resolve, reject) => {
    setTimeout(function(){
      resolve('hello world');
    }, time)
  });
};

test(1000).then((v) => {
  console.log(v);
});

若是改用 async/await 代碼以下:get

var testAsync = function(time) {
  return new Promise((resolve, reject) => {
    setTimeout(function(){
      resolve('hello world');
    }, time)
  });
};

async function test(time) {
  const v = await testAsync(time);
  console.log(v); // hello world
}
test(1000);

看上面的代碼,反而會以爲 使用 async/await 代碼變得多一點,複雜一點,可是結果貌似都同樣,那麼使用 async/await的優點在哪?

1-4 async/await的優點在於處理then鏈

單一的Promise鏈貌似不能發現 async/await的優點,可是若是須要處理多個Promise組成的then鏈的時候,優點能夠看出來,由於Promise是經過then鏈來解決多層回調的問題,如今咱們又可使用
async/await來進一步優化,他們的優勢就是解決多層異步回調的嵌套。

假設咱們如今有一個需求是,分多個步驟完成,每一個步驟都是異步的,而且後面的異步都須要依賴於上一個異步回調返回的數據,進行往下傳遞。咱們先用 setTimeout來模擬異步操做。

function useTimeout (t) {
  return new Promise((resolve, reject) => {
    setTimeout(()=> {
      resolve(t+100)
    }, t);
  });
}

function step1(t) {
  console.log(`step1 with ${t}`); // step1 with 300
  return useTimeout(t);
}

function step2(t) {
  console.log(`step2 with ${t}`); // step2 with 400
  return useTimeout(t);
}

function step3(t) {
  console.log(`step3 with ${t}`); // step3 with 500
  return useTimeout(t);
}

function test() {
  const time1 = 300;
  step1(time1)
    .then(time2 => step2(time2))
    .then(time3 => step3(time3))
    .then(res => {
      console.log(`result is ${res}`);  // result is 600
    })
} 
test();

若是咱們使用 async/await來實現,代碼變爲以下:

function useTimeout (t) {
  return new Promise((resolve, reject) => {
    setTimeout(()=> {
      resolve(t+100)
    }, t);
  });
}

function step1(t) {
  console.log(`step1 with ${t}`); // step1 with 300
  return useTimeout(t);
}

function step2(t) {
  console.log(`step2 with ${t}`); // step2 with 400
  return useTimeout(t);
}

function step3(t) {
  console.log(`step3 with ${t}`); // step3 with 500
  return useTimeout(t);
}

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

上面咱們能夠看到 使用async/await 代碼看起來都是同步的,等第一步完成後,再執行第二步,依次類推..... 而且不須要更多的回調函數嵌套。

下面咱們再來看下咱們以前講的,後面的步驟須要上一個步驟的結果傳遞進去,使用async/await的優點可能更明顯。
以下代碼:

function useTimeout (t) {
  return new Promise((resolve, reject) => {
    setTimeout(()=> {
      resolve(t+100)
    }, t);
  });
}

function step1(t1) {
  console.log(`step1 with ${t1}`); // step1 with 300
  return useTimeout(t1);
}

function step2(t1, t2) {
  console.log(`step2 with ${t1} and ${t2}`); // step2 with 300 and 400
  return useTimeout(t1+t2);
}

function step3(t1, t2, t3) {
  console.log(`step3 with ${t1} and ${t2} and ${t3}`); // step3 with 300 and 400 and 800
  return useTimeout(t1+t2+t3);
}

async function test() {
  const time1 = 300;
  const time2 = await step1(time1);
  const time3 = await step2(time1, time2);
  const result = await step3(time1, time2, time3);
  console.log(`result is ${result}`);  // result is 1600
} 
test();

1-5 捕捉錯誤
咱們可使用 try catch 來捕獲錯誤,以下代碼:

var sleep = function (time) {
  return new Promise((resolve, reject) => {
    setTimeout(function() {
      // 出錯了, 返回 error
      reject('error');
    }, time);
  })
};

var start = async function() {
  try {
    console.log('start');
    await sleep(3000); // 返回一個錯誤
    // 下面代碼不會被執行
    console.log('end');
  } catch (err) {
    console.log(err); // 捕捉錯誤 error 
  }
};

start();
相關文章
相關標籤/搜索