JS循環中正確使用async、await的姿勢分享

概覽(循環方式 – 常用)

  • for
  • map
  • forEach
  • filter

聲明遍歷的數組和異步方法

聲明一個數組:⬇️

const skills = ['js', 'vue', 'node', 'react']

再聲明一個promise的異步代碼: ⬇️

function getSkillPromise (value) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(value)
    }, 1000)
  })
}

for 循環中使用

由於for循環並非函數,而async、await需要在函數中使用,因此需要在for循環外套一層function

async function test () {
  for (let i = 0; i < skills.length; i++) {
    const skill = skills[i]
    const res = await getSkillPromise(skill)
    console.log(res)
  }
}

test() // 調用

當使用await時,希望JavaScript暫停執行,直到等待 promise 返回處理結果。上述結果意味著for循環中有異步代碼,是可以等到for循環中異步代碼完全跑完之後再執行for循環後面的代碼。

但是他不能處理回調的循環,如forEach、map、filter等,下面具體分析。

map 中使用

在map中使用await, map 的返回值始是promise數組,這是因為異步函數總是返回promise。

async function test () {
  console.log('start')
  const res = skills.map(async item => {
    return await getSkillPromise(item)
  })
  console.log(res)
  console.log('end')
}

test()

結果:始終為promise數組

start
[
  Promise { <pending> },
  Promise { <pending> },
  Promise { <pending> },
  Promise { <pending> }
]
end

若果你想要等到promise的返回結果,可以使用promise.all()處理一下

async function test () {
  console.log('start')
  const res = skills.map(async item => {
    return await getSkillPromise(item)
  })
  const resPromise = await Promise.all(res)
  console.log(resPromise)
  console.log('end')
}

test()

// 結果
start
[ 'js', 'vue', 'node', 'react' ]
end

forEach 中使用

先上代碼和結果

async function test () {
  console.log('start')
  skills.forEach(async item => {
    const res = await getSkillPromise(item)
    console.log(res)
  })
  console.log('end')
}

test()

預期結果

‘Start’

‘js’

‘vue’

‘node’

‘react’

‘End’

實際結果 在forEach循環等待異步結果返回之前就執行瞭console.log(‘end’)

‘Start’

‘End’

‘js’

‘vue’

‘node’

‘react’

JavaScript 中的 forEach不支持 promise 感知,也支持 async 和await,所以不能在 forEach 使用 await 。

filter 中使用

使用filter過濾item為vue或者react的選項

正常使用 filter:

async function test () {
  console.log('start')
  const res = skills.filter(item => {
    return ['vue', 'react'].includes(item)
  })
  console.log(res)
  console.log('end')
}

test() // 調用

// 結果
start
[ 'vue', 'react' ]
end

使用 await後:

async function test () {
  console.log('start')
  const res = skills.filter(async item => {
    const skill = await getSkillPromise(item)
    return ['vue', 'react'].includes(item)
  })
  console.log(res)
  console.log('end')
}

test()

預期結果:

start

[ ‘vue’, ‘react’ ]

end

實際結果:

[ ‘js’, ‘vue’, ‘node’, ‘react’ ]

end

結論:因為異步函數getSkillPromise返回結果返回的promise總是真的,所以所有選項都通過瞭過濾

附使用小結

  1. 如果你想連續執行await調用,請使用for循環(或任何沒有回調的循環)。
  2. 永遠不要和forEach一起使用await,而是使用for循環(或任何沒有回調的循環)。
  3. 不要在 filter 和 reduce 中使用 await,如果需要,先用 map 進一步驟處理,然後在使用 filter 和 reduce 進行處理。

結語:由於工作中遇到瞭超大表單抽離組件,異步校驗是遇到瞭此問題,後來經過查閱資料總結出來的結果

總結

到此這篇關於JS循環中正確使用async、await的文章就介紹到這瞭,更多相關JS循環中使用async、await內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: