数组的reduce方法

async await reduce array

大家对数组的map,filterforEach等的操作应该都比较熟悉了。这两天写代码的时候用到了reduce方法,一不小心写出了一个bug,在此记录一下。

首先,reduce的用法如下:

对数组中的所有元素调用指定的回调函数。该回调函数的返回值为累积结果,并且此返回值在下一次调用该回调函数时作为参数提供。

语法:

array.reduce(callback[,initialValue]) //注意这时候只能是同步方法
function callbackfn(previousValue, currentValue, currentIndex, array1)
参数 含义
previousValue 通过上一次调用回调函数获得的值。如果向 reduce 方法提供initialValue,则在首次调用函数时,previousValue 为 initialValue。否者将是调用数组的第一项
currentValue 当前数组元素的值。
currentIndex 当前数组元素的数字索引。
array1 包含该元素的数组对象。

实现:

// 实现数组的每一项之和
var arr = [1,2,3,4]
arr.reduce((pre,cur) => {return pre + cur}) // return 10
实现数组的每一项转化为对象,例({1: 1, 2: 2, 3: 3, 4: 4})
var arr = [1,2,3,4]
arr.reduce((final,cur) => {
  final[cur] = cur
  return final
}, {}) // return {1: 1, 2: 2, 3: 3, 4: 4}

BUG
昨天的代码,我是这么实现的:

async function getGroup() {
    ...
}

async function getGroups() {
  var arr = [1,2,3]
  const result = arr.reduce(async (final,cur) => {
    final[cur] = await getGroup(cur)
    console.log(final, '<===final')
    return final
  }, {}) 
}
// final的打印值
{ '9ddc9834-9344-4cc1-be38-ba2d0e9d17c5': { recommendType: 1, weight: 123 } } '<===final'
Promise {
  _c: [],
  _a: undefined,
  _s: 1,
  _d: true,
  _v: { '9ddc9834-9344-4cc1-be38-ba2d0e9d17c5': { recommendType: 1, weight: 123 } },
  _h: 0,
  _n: false,
  '9bb6ed56-29a3-47e5-89a8-b652e8f08ef8': { recommendType: 2, weight: 12 } } '<===final'
Promise {
  _c: [],
  _a: undefined,
  _s: 0,
  _d: false,
  _v: undefined,
  _h: 0,
  _n: false,
  '30ddd8c9-2132-4d27-bc4b-4d27305acec9': {} }'<===final'

我们可以看到final的值并不是我们预期的,循环中只有第一个值是对的,后面的值都不对,而且看起来是个Promise对象。这是为什么呢?
接下来看到上面的实现翻译成reduce的底层实现方式:

var final = {}
async function getGroup(final, cur){
  final[cur] = await getGroup(cur)
  console.log(final, '<===final')
  return final
}
for(var i = 0, i < arr.lenght, i++) {
   final = getGroup(final, arr[i])
   //这里没有用async await执行异步方法,导致,传回的final只是个Promise方法对象
}

这样我们就清楚为什么上面会打印这么奇怪的结果了。下面我们只要做小小的修改,就可以得到正确的结果:

var temp = {}
async function getGroup() {
    ...
}

async function getGroups() {
  var arr = [1,2,3]
  const result = arr.reduce(async (final,cur) => {
    temp[cur] = await getGroup(cur)
    console.log(temp, '<===final')
    return temp
  }, {}) 
}

以后还是尽量避免在reduce里面执行异步方法~


朱珍珍
75 声望7 粉丝

毕业于重庆邮电大学,暂就职在北京杏树林科技有限公司,JS开发


下一篇 »
SQL