JavaScript Array.filter uniqes 而不是阻塞 UI



我有一个特定的用例,其中必须在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响应(或至少重新绘制(的几种方法;但是,由于我处理重复项,因此我的情况有点棘手。

我想将数组分解为块并在setTimeout(对于 UI(内的循环中运行Array.filter部分之上,但我稍后无论如何都需要将这些块与它们进行比较,所以它只会延长逻辑!我对尝试员工感到不够舒服,因为组织中有些浏览器不支持这些浏览器。

有谁知道如何解决这个问题?不可以,无法将其移动到后端:(

问候

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

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

这使得人们通过数组,并利用属性名称查找的内部效率而不是.indexOf()的顺序搜索。对于具有大量元素的初始数组,这应该在相对较短的时间内运行。

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

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

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

[...new Set(items)]

注意:仅当 Items 数组仅包含基元值时,这才有效

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

最新更新