JavaScript Array.filter唯一并且不阻止UI

问题描述 投票:0回答:3

我有一个特定的用例,其中某些验证逻辑必须在UI中发生(出于各种业务原因[...])。该阵列最多可包含数十个或数十万个项目(1-400K)。前端基于Angular。

第一步是检查重复项(并将它们存储在另一个数组中[...])。这是通过以下方式完成的:

validateTargets(targets: string[]): ValidationResultObject[] {

    let result: ValidationResultObject[];
    let dups: string[] = [];

    var uniques = targets.filter( (item,index) => {
        if (targets.indexOf(item) === index) {
        return targets.indexOf(item) === index
        }
        else {
            dups.push(targets[index])
        }
    }

    //other validation logic goes here

    return result;
}

问题是当遇到超过50K的任何内容时,UI明显冻结。目前,我已经在setTimeout的另一个函数中作为回调放置在上面,以至少允许UI在页面挂起时运行微调器:)

[我已经看到人们建议如何设计代码以允许UI响应(或至少重新绘制)的几种方法;但是,由于我处理重复项,因此我的情况有些棘手。

我曾想将数组分解为块,并在Array.filter(对于UI)内循环运行在setTimeout部分之上,但后来我仍然需要将块与自身进行比较,因此只会延长逻辑!我感觉不够舒适,无法尝试使用工作人员,因为组织中有不支持这些工作的浏览器。

有人知道如何解决这个问题吗?不,无法将其移至后端:(

问候

javascript typescript loops browser array-filter
3个回答
1
投票

您可以更有效地过滤出重复项:

let filtered = targets.reduce((result, item) => {
  result[item] = 1;
  return result;
}, {});
let noDuplicates = Object.keys(filtered);

这将遍历数组,并在.indexOf()的顺序搜索中利用属性名称查找的内部效率。对于具有大量元素的初始数组,这应该在相当短的时间内运行。


0
投票

我从未遇到过这种情况,但是我想问一下您是否在JavaScript中使用了Set类型,因为它在内部删除了重复项,并且比过滤器JS Set vs Array更有效,并且如果您使用的浏览器不支持Set,您仍然可以使用一个polyfill。


0
投票

您可以使用asynchronous函数来处理此数据量。完成后,调用一个以结果为参数的回调,以在完成后继续正常流程。

async validateTargets(targets: string[], callback: function): {
 //...Logic
 callback(result)
}

此外,要删除重复项,可以使用

[...new Set(items)]

注意:仅在Items数组仅包含原始值时,此方法才有效

© www.soinside.com 2019 - 2024. All rights reserved.