async
await
reduce
array
數組
你們對數組的map
,filter
,forEach
等的操做應該都比較熟悉了。這兩天寫代碼的時候用到了reduce方法,一不當心寫出了一個bug,在此記錄一下。異步
首先,reduce的用法以下:async
對數組中的全部元素調用指定的回調函數。該回調函數的返回值爲累積結果,而且此返回值在下一次調用該回調函數時做爲參數提供。函數
語法:翻譯
array.reduce(callback[,initialValue]) //注意這時候只能是同步方法
function callbackfn(previousValue, currentValue, currentIndex, array1)
參數 | 含義 |
---|---|
previousValue | 經過上一次調用回調函數得到的值。若是向 reduce 方法提供initialValue,則在首次調用函數時,previousValue 爲 initialValue。否者將是調用數組的第一項 |
currentValue | 當前數組元素的值。 |
currentIndex | 當前數組元素的數字索引。 |
array1 | 包含該元素的數組對象。 |
實現:code
// 實現數組的每一項之和 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方法對象 }
這樣咱們就清楚爲何上面會打印這麼奇怪的結果了。下面咱們只要作小小的修改,就能夠獲得正確的結果:get
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裏面執行異步方法~回調函數