2017-08-03 22 views
0

我幾乎肯定必須有一個解釋,但我只花了一個多小時試圖找出爲什麼我的異步代碼出現在早期嘗試使用ary.filter()轉換數組時遇到問題,但是當我使用ary.map()時,異步會解決問題。任何人都可以幫助闡明這個話題,不勝感激!async/await:使用Array.prototype.map(工作)與Array.prototype.filter(不工作)的異步數組轉換

我也使用節點8.2.1只是爲了清楚。

所以提供一些代碼和輸出對問題進行描述,這裏是使用ary.map工作,並提供在控制檯下面的輸出的一個例子。

(async() => { 
    const timeStart = Date.now() 
    const ary = new Array(20).fill(0).map((v, i) => i+1) 

    const newAry = await Promise.all(
    ary.map(async val => { 
     return await new Promise((resolve, reject) => { 
     setTimeout(() => resolve(val*2), 1000) 
     }) 
    }) 
) 
    console.log('original ary', ary) 
    console.log('newAry is', newAry) 
    const timeEnd = Date.now() 
    console.log(timeEnd - timeStart, 'milliseconds between start and end') 
})() 

輸出到控制檯如下:

original ary [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 ] 
newAry is [ 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40 ] 
1022 milliseconds between start and end 

所以如你所期望,有〜當原始數組轉換在1秒,如預期的輸出。

以下代碼非常相似,但使用ary.filter(),並且不是按預期返回。

(async() => { 
    const timeStart = Date.now() 
    const ary = new Array(20).fill(0).map((v, i) => i+1) 

    const newAry = await Promise.all(
    ary.filter(async val => { 
     return await new Promise((resolve, reject) => { 
     setTimeout(() => resolve(Math.random() < 0.5), 1000) 
     }) 
    }) 
) 
    console.log('original ary', ary) 
    console.log('newAry is', newAry) 
    const timeEnd = Date.now() 
    console.log(timeEnd - timeStart, 'milliseconds between start and end') 
})() 

輸出如下:

original ary [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 ] 
newAry is [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 ] 
18 milliseconds between start and end 

爲什麼ary.filter()不變換所述陣列和使用異步/ AWAIT當在適當的時間分辨方面表現一樣ary.map()

+0

請閱讀整篇文章,如果需要在您有權訪問的計算機上本地運行代碼,以便您可以查看該行爲。 –

回答

2

調用Promise.all()只對承諾數組有意義。

.map()返回其回調的結果,如果回調是異步的,則返回結果爲承諾。因此,這工作正常。

.filter()將其回調的結果視爲布爾值(它不是),然後返回原始數組中的項目。

+0

Ahhh謝謝我認爲我明白了,但只是爲了確認,因爲在我的示例中,我向'.filter()'返回了一個承諾,這總是很糟糕,我會得到原始數組的所有元素?我假設沒有一個解決方法,除了一些我肯定存在於bluebird中的實用程序(如果可能的話,嘗試使用本地promise)或者編寫一些額外的代碼行來使用.map以某種方式返回true/false然後過濾該數組? –

+0

@ LanceWhatley:對。 – SLaks

+0

再次感謝,由於時間不夠而無法接受您的答案,但很快就會接受。 –