天天看點

async/await 和 promise 的用法async/await 和 promise 的用法

async/await 和 promise 的用法

參考:https://www.jianshu.com/p/ffa5cbe9ab29

async/await ”vs“ promise

寫法:

Promise

主要用then函數的鍊式調用,一直點點點,是一種從左向右的橫向寫法。

async/await

從上到下,順序執行,就像寫同步代碼一樣。這更符合人編寫代碼的習慣

參數數量

Promise

的then函數隻能傳遞一個參數,雖然可以通過包裝成對象,但是這會導緻傳遞備援資訊,頻繁的解析又重新組合參數,比較麻煩。

async/await

沒有這個限制,就當做普通的局部變量來處理好了,用let或者const定義的塊級變量,想怎麼用就怎麼用,想定義幾個就定義幾個,完全沒有限制,也沒有備援的工作。

機制

Promise

是根據函數式程式設計的範式,對異步過程進行了一層封裝。

async/await

是基于協程的機制,是真正的“儲存上下文,控制權切換 ... ... 控制權恢複,取回上下文”這種機制,是對異步過程更精确的一種描述。

async/await

async/await

是基于

Promise

的,是進一步的一種優化。不過再寫代碼的時候,

Promise

本身的API出現得很少,很接近同步代碼的寫法。

async

隻是表明裡面可能有異步過程,裡面可以有

await

關鍵字,如果沒有

async

函數本身會馬上傳回,不會阻塞目前線程。它的函數的傳回值是一個

Promise

對象。

return new Promise();

則直接處理promise對象

return data;

則相當于

Promise.resolve(data);

還是一個

Promise

對象

兩者都需要用用

.then(data => { })

函數處理。

await

的是

resolve(data)

消息,并把資料

data

傳回。比如,下面代碼中,當

Promise

對象由

Pending

變為

Resolved

的時候,變量

a

就等于

data

;然後再順序執行下面的語句`console.log(a);

const a = await new Promise((resolve, reject) => {
    // async process ...
    return resolve(data);
});
console.log(a);
           

await

等待的雖然是

promise

對象,但不必寫

.then(..)

,直接可以得到傳回值。

通過

await

标記的方法,隻有該方法執行完成之後才能往後執行

async function asyncFunction() {
    console.time('asyncFunction total executing:');
    const sleep1 = await sleep(2000);
    console.log('sleep1: ' + sleep1);
    const [sleep2, sleep3, sleep4]= await Promise.all([sleep(2000), sleep(1000), sleep(1500)]);
    console.log('sleep2: ' + sleep2);
    console.log('sleep3: ' + sleep3);
    console.log('sleep4: ' + sleep4);
    const sleepRace = await Promise.race([sleep(3000), sleep(1000), sleep(1000)]);
    console.log('sleep race: ' + sleepRace);
    console.timeEnd('asyncFunction total executing:');
    return 'asyncFunction done.'  // 這個可以不傳回,這裡隻是做個标記,為了顯示流程
}
           
  • sleep1: sleep for 2000 ms

    這是第一個

    await

    之後的第一個異步過程,後面的代碼,不論是同步和異步,都在等他執行完畢。
  • sleep2 ~ sleep4

    這是第二個

    await

    之後的

    Promise.all()

    異步過程。這是“比慢模式”,三個

    sleep

    都完成後,再運作下面的代碼s,耗時最長的是

    2000ms

  • sleep race: sleep for 1000 ms

    這是第三個

    await

    之後的

    Promise.race()

    異步過程。這是“比快模式”,耗時最短

    sleep

    都完成後,就運作下面的代碼。耗時最短的是

    1000ms

  • asyncFunction total executing:: 5006.276123046875ms

    這是最後的統計總共運作時間代碼。三個await之後的異步過程之和

異常捕獲

對于異常的捕獲,除了傳統的try/catch

async getData() {
  try {
    this.formInfos = await getFormInfos();
  } catch (e) {
    Toast(`資料擷取失敗,請稍後重試`)
  }
}
           

也可以通過.catch去捕獲異常

let books = await bookModel.fetchAll()
  .catch((error) => { console.log(error); });
           

結合之後使用

const responseJson = await Promise.race([
  fetch(url, requestConfig),
  new Promise(function (resolve, reject) {
    setTimeout(() => reject(new Error('request timeout')), 5000)
  })
])
.then((resPromise) => {
  let resultPromise = resPromise.json()
  return resultPromise
}).then((result) => {
  return result
}).catch((e)=>{
  throw new Error("網絡出現問題~")
})

if (responseJson['success']) {
  return responseJson['obj']
} else {
  throw new Error(responseJson['msg'])
}
           

注意:

  • await

    隻能放在

    async

    函數内部使用,不能放在普通函數裡面,否則會報錯。
  • 後面放

    Promise

    對象,在

    Pending

    狀态時,相應的協程會交出控制權,進入等待狀态。這個是本質。
  • await

    後面也可以跟同步代碼,不過系統會自動轉化成一個

    Promise

    對象。 比如

    const a = await 'hello world';

    其實就相當于

    const a = await Promise.resolve('hello world');

  • await

    隻關心異步過程成功的消息

    resolve(data)

    ,拿到相應的資料

    data

    。至于失敗消息

    reject(error)

    ,不關心(可以放在一個

    try...catch

    結構中統一處理)

Promise

promise代表非阻塞異步執行的抽象,所謂的非阻塞異步執行就是,promise執行的時候,其他程式可以繼續往下執行,不必像await一樣,需要等待。

console.log('Starting Execution');

const promise = rp('http://example.com/');
promise.then(result => console.log(result));

console.log("Can't know if promise has finished yet...");
           
async/await 和 promise 的用法async/await 和 promise 的用法

正确的使用方式

// 錯誤示範
async getBooksAndAuthor(authorId) {
  const books = await bookModel.fetchAll();
  const author = await authorModel.fetch(authorId);
  return {
    author,
    books: books.filter(book => book.authorId === authorId),
  };
}
// 這裡await之後就會阻塞,執行完一個執行下一個

// 正确姿勢
async getBooksAndAuthor(authorId) {
  const bookPromise = bookModel.fetchAll();
  const authorPromise = authorModel.fetch(authorId);
  const book = await bookPromise;
  const author = await authorPromise;
  return {
    author,
    books: books.filter(book => book.authorId === authorId),
  };
}
// promise會異步執行,的帶結果之後執行await

           

繼續閱讀