優化JS中的Async/Await 使用

JS中調用 async 函數時會返回一個 Promise 對象(隱式轉換)。當async 函數返回一個值時,Promise 的 resolve 方法會負責傳遞這個值,當 async 函數拋出異常時,Promise 的 reject 方法也會傳遞這個異常值。
在async 函數中如果遇見 await 表達式,則 async 函數會暫停執行,等待表達式中的 Promise 解析完成後繼續執行 async 函數並返回結果。

基於上面的定義,我們來對比一下如下的代碼,我們就知道優化點如何排查了。

function resolveAfter2Seconds(x) {
  return new Promise(resolve =>setTimeout(() =>  resolve(x), 2000))
}

async function fn1(x) {
  var a = resolveAfter2Seconds(20)
  var b = resolveAfter2Seconds(30)
  return x + await a + await b
}

// prints 60 after 2 seconds
fn1(10).then(v => console.log(v))

async function fn2(x) {
  var a = await resolveAfter2Seconds(20)
  var b = await resolveAfter2Seconds(30)
  return x + a + b
}

// prints 60 after 4 seconds
fn2(10).then(v => console.log(v))

上面的代碼演示代碼中,我們可以發現,不同的 await 位置聲明,會直接影響到函數執行的時間。
同時,我們在處理 async 函數的返回時,針對其 reject 的場景時,try-catch 模塊來進行捕獲,但由於try-catch會創建獨立的作用域(這算是很老的一個點了,不知新版的V8有沒有進行過優化),所以會在性能上有一些損失,但是相對於代碼的可讀性,這一點損失也無所謂啦。

async function fn(url) {
  let v
  try {
    v = await doSomething(url)
  } catch (e) {
    v = await handlerError(url)
  }
  return success(v)
}

// 比價醜陋的寫法,通過犧牲代碼的可讀性來避免作用域的開闢

async function fn(url) {
  let v
  v = await doSomething(url).catch(err => {
      v = await handlerError(url)
  })
  return success(v);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章