代码之家  ›  专栏  ›  技术社区  ›  Nibor

es6:将数组分块过滤以不冻结ui

  •  1
  • Nibor  · 技术社区  · 8 年前

    我正试图过滤一个巨大的数组。不幸的是,数组太大,以至于用户界面冻结。这就是为什么我试图在组间执行超时的过滤,这样UI就可以加载。

    为了演示,我使用了“巨大”数组 [1,2,3,4,5] 并返回可被2除的元素。

    我试过了,但没用:

    [1,2,3,4,5].filter(async (x) => {
        // wait 1 sec after each element to filter
        await new Promise(resolve => setTimeout(resolve, 1000));
        return x % 2 === 0;
    });
    

    有没有办法过滤一个大数组,这样用户界面就不会冻结?

    2 回复  |  直到 8 年前
        1
  •  0
  •   Sergio Mazzoleni    8 年前

    Array.prototype.filter 无法使用 async 谓词,因为谓词必须返回布尔值,但是 异步 谓词将返回一个promise。

    你可以使用 Array.prototype.reduce 链接异步调用并自己构造筛选结果。

    async function filterAsync(array, predicate) {
        const res = [];
    
        await array.reduce(async (promise, n) => {
            await promise;
            if (await predicate(n)) {
                res.push(n);
            }
        }, Promise.resolve());
    
        return res;
    }
    
    
    filterAsync([1, 2, 3, 4, 5], async x => {
        // wait 1 sec after each element to filter
        await new Promise(resolve => setTimeout(resolve, 1000));
        return x % 2 === 0;
    }).then(console.log);
    
        2
  •  0
  •   Jingshao Chen    8 年前

    您可以以异步方式填充带有过滤元素的空数组,警告是顺序可能与原始数组不相同:

    var ret = []
    var promiseArray = [1,2,3,4,5].map( async x => {
        await new Promise(resolve => {setTimeout(resolve, 1000)})
        if (x % 2 === 0) {
            ret.push(x)
        }
    })
    Promise.all(promiseArray).then(()=> {console.log(ret)})