面試向:Async/Await 代替 Promise.all()

圖片描述

新調料,新味道

基本概念

Promise

保存着一個將來可用的值的代理,自己是嚴格按照異步方式執行的javascript

function resolveUnderThreeSeconds(delay) {
  return new Promise(function(resolve, reject) {
    setTimeout(() => resolve('success'), delay)
    setTimeout(() => reject('fail'), 3000)
  })
}

resolveUnderThreeSeconds(2000)
  .then(res => {
    console.log('res', res)
  })
  .catch(err => {
    console.log('err', err)
  })

編寫異步代碼時,可能兩個任務中的一個任務會依賴另外一個任務的結果,所以這兩個任務必須串行執行java

Promise.all() 方法接受一個 Promise 數組,數組內全部 Promise 執行成功後,根據傳入順序返回各個 Promise 的結果數據,其中一個被拒絕,即會暫停,返回錯誤信息git

const p1 = Promise.reject('failed')
const p2 = Promise.resolve('success')
const p3 = Promise.resolve('success')
const p = Promise.all([p1, p2, p3]).catch(err => console.log(err))

Async/Await

async 函數兼顧了基於 Promise 的實現和生成器風格的同步寫法github

function resolveAfter2Seconds() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('resolved');
    }, 2000);
  });
}

async function asyncCall() {
  console.log('calling');
  var result = await resolveAfter2Seconds();
  console.log(result);
  // expected output: 'resolved'
}

asyncCall();

實現

功能分析

關鍵:Promise.all() 傳入的是 promise 數組,數組內全部 Promise 執行成功後,根據傳入順序返回各個 Promise 的結果數據,其中一個被拒絕,即會暫停,並返回錯誤信息面試

數組進入 async 函數,循環使用 async/await 執行進入的數組函數,而後將函數結果組成數組,最後返回該數組便可數組

try/catch 可獲取 async 函數內,任意 await 的錯誤,便可知足 其中一個被拒絕,即會暫停,並返回錯誤信息 的功能promise

async function asyncAlls(jobs) {
  try {
    // 循環執行
    let results = jobs.map(async job => await job)
    let res = []
    // 組合數組
    for (const result of results) {
      res.push(await result)
    }
    return res
  } catch (error) {
    throw new Error(error)
  }
}

實例展現

function doJob(x, sec) {
  if (!x) {
    throw new Error('test error')
  }
  return new Promise(resolve => {
    console.log('Start: ' + x)
    setTimeout(() => {
      console.log('End: ' + x)
      resolve(x)
    }, sec * 100)
  })
}

async function asyncAlls(jobs) {
  try {
    let results = jobs.map(async job => await job)
    let res = []
    for (const result of results) {
      res.push(await result)
    }
    return res
  } catch (error) {
    throw new Error(error)
  }
}
(async function() {
  try {
    const all1 = await asyncAlls([doJob(1, 1), doJob(2, 1), doJob(0, 1), doJob(4, 1)])
    console.log('all1', all1)
  } catch (error) {
    console.log('0', error)
  }
  try {
    const all2 = await asyncAlls([doJob(5, 1), doJob(6, 1), doJob(7, 1), doJob(8, 1)])
    console.log('all2', all2)
  } catch (error) {
    console.log('1', error)
  }
})()

總結

本文思路源於一個面試題,迫於好奇,花了點時間實現了一下,期間有諸多不懂的地方也請教了許多小夥伴,感謝諸位小夥伴解惑異步

本文例子僅供學習,不建議應用與實戰項目async

感謝閱讀

參考

JavaScript Async/Await: Serial, Parallel and Complex Flow
ES6 系列之咱們來聊聊 Async函數

原文閱讀

相關文章
相關標籤/搜索