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())
      }
    }
  }
复制代码
相关文章
相关标签/搜索