JS循環中的中斷、異步for...in、forEach、 map

Array.prototype.forEach

forEach方法對數組的每一個元素執行一次提供的函數。 語法: arr.forEach(callback[, thisArg]); 參數:數組

  1. callback(currentValue, index?, array?) 問好表示可選
  2. thisArg可選參數。當執行回調函數時用做 this 的值(參考對象)。

關於異步

forEach是並行的對每一個元素執行函數。因此await不會阻礙循環和代碼的執行瀏覽器

const arr = [1, 2, 3]
  async function wait (time) {
    const now = Date.now()
    return new Promise((res, rej) => {
      setTimeout(() => {
        console.log('我是異步執行的函數')
        res()
      }, time)
    })
  }

  arr.forEach(async (item) => {
    await wait(1000)
    console.log(item)
    return item * 2
  })
  console.log(arr) 

複製代碼

打印結果爲: bash

緣由:forEach中的異步函數不生效,因此會直接執行 console.log(arr),大約1秒後會執行完異步函數,而後執行對應的console.log(item).這裏的執行順序和瀏覽器的event loop機制相關。 若是想要確保異步代碼執行完成後再繼續執行,能夠使用Promise.all。上面的代碼能夠改寫成:

const arr = [1, 2, 3]

  async function wait (time) {
    const now = Date.now()
    return new Promise((res, rej) => {
      setTimeout(() => {
        console.log('我是異步執行的函數')
        res()
      }, time)
    })
  }
  let asyncFuncs = []
  arr.forEach(async (item) => {
    asyncFuncs.push(wait(1000))
    console.log(item)
    return item * 2
  })
  Promise.all(asyncFuncs).then(() => {
    console.log(arr)
  })

複製代碼

注意點: forEach循環裏不能有break或continue, 會產生報錯 callback能夠使用return但return的結果沒有做用,只是提早結束函數運行,也就是calback老是返回undefined forEach返回值undefined異步

Array.prototype.map

map方法和forEach類似,但map方法會建立一個新數組,其結果是該數組中的每一個元素都調用一個提供的函數後返回的結果。 參數:和forEach相同async

注意點: 異步函數執行上map和forEach相同,await不生效 循環裏不能有break或continue, 會產生報錯 callback的return 返回新的數組元素,不使用return時等價於返回undefined函數

const array = [1, 4, 9, 16]
const map = array.map(x => x * 2)
console.log(map) // [2,8,18,32]

複製代碼

for

使用:for(let i = 0; i < 10; i += 1){}oop

關於異步函數

await在for循環中是生效的,即,循環會一個完成後繼續執行下一個。ui

關於break和continue

for循環中能夠使用break continue。break會結束循環,繼續執行代碼。continue是結束本次循環。this

注意: for循環中沒有return。若是使用會產生報錯Uncaught SyntaxError: Illegal return statementspa

for...of

for...of語句在可迭代對象上建立一個迭代循環,執行語句。可迭代對象是指對象具備Iterator接口。也就是若是一個變量具備Iterator接口,就能夠用for..in方法去循環遍歷。Array和Map都是可迭代對象,但對象上是沒有iterator接口的。若是想在對象上使用iterator方法,能夠在對象的Symbol.iterator上寫個Iterator函數。例如:

const person = {
    name: 'Amy',
    age: 18,
    [Symbol.iterator] () {
      return Object.keys(this)[Symbol.iterator]()
    }
  }
  for (let item of person) {
    console.log(item)
  } // 控制檯會輸出 name 和 age

複製代碼

關於異步函數

和for循環同樣,會等待await執行完後繼續執行。例如:

async function wait (time) {
    const now = Date.now()
    return new Promise((res, rej) => {
      setTimeout(() => {
        console.log('我是異步執行的函數')
        res()
      }, time)
    })
  }

  const arr = [1, 2, 3]

  async function test () {
    for (let i of arr) {
      console.log(i)
      await wait(1000)
    }
  }

  test()

複製代碼

執行結果:

關於continue和break

和for循環相同, break跳出循環;continue跳出本次循環繼續執行 例如:

const arr = [1, 2, 3]
  for (let i of arr) {
    if (i === 2) {break}
    console.log(i)
  } // 會輸出1

複製代碼

注意: 沒有return 會報錯

for...in

異步執行

和 for 循環及for..of同樣依次執行代碼。

break和continue

忽略break和continue for...in中也沒有return

總結:

  1. forEach和map,await不生效;使用break或continue會報錯
  2. for循環、for...in,for...of,支持await,for和for...of中能夠使用break和continue;for...in會忽略continue和break

開發過程當中,根據使用場景,有些能夠並行執行,有些狀況須要依次執行一組異步函數。能夠封裝一個方法來執行。

/* * 並行執行一組方法 * @params {Array<Object>} funcArr 一組待執行的函數{func: asyncFunc, params: funcParams} * @returns {Array<Promise>} 函數執行結果(按數組順序返回) * @example * excuteInParallel([{func: asynFuc1, params: 2},{func: asynFuc2, params: {param: 1}}}]) * */
  let ret = []

  async function excuteInParallel (funcArr = []) {
    const result = funcArr.map((item) => {
      if (item.params) {
        return item.func(item.params)
      }
      return item.func()
    })
    return Promise.all(result)
  }
/* * 串行執行一組異步方法 * @params {Array<Object>} funcArr 一組待執行的函數{func: asyncFunc, params: funcParams} * @returns {Array<Promise>} 函數執行結果(按數組順序返回) * @example * excuteInParallel([{func: asynFuc1, params: 2},{func: asynFuc2, params: {param: 1}}}]) * */
  async function excuteInSeries (funcArr = []) {
    const result = []
    for (const item of funcArr) {
      if (item.params) {
        result.push(await item.func(item.params))
      } else {
        result.push(await item.func())
      }
    }
  }
複製代碼
相關文章
相關標籤/搜索