我有一个大的(~10,000项)对象从JSON文件中读取并存储为局部变量,格式如下:
{
"some_uuid_1" : {"code":"some_code_1", "name":"asdf"},
"some_uuid_2" : {"code":"some_code_2", "name":"qwer"},
...
"some_uuid_n" : {"code":"some_code_n", "name":"zxcv"}
}
我想遍历整个主对象,将每个元素的name
属性与某个变量checkName
进行比较,并将元素的code
属性附加到DOM元素(如果有)比赛,如此:
function myFilter(checkName)
{
var myArray = Object.values(myObj);
for (var i = 0; i < myArray.length; i++)
{
if (myArray[i]["name"] == checkName)
{
$("#someElement").append(`${myArray[i]["code"]} <br />`);
}
}
}
但是,由于对象的大小非常大,我想异步运行该函数,以便在浏览器运行时不会冻结它。我不介意在其他代码运行时是否在后台缓慢填充DOM元素#someElement
。
我如何使用JavaScript和/或JQuery实现这一目标?
答案 0 :(得分:2)
对于现代浏览器来说,即使是10k项目也不会过于密集。真正的时间接收器是append
,它导致浏览器在与名称匹配的循环的每次迭代中reflow/repaint。
这可以通过将所有匹配组合成一个字符串然后将该字符串附加一次来避免。
const codes = Object.values(myObj).filter(({name}) => name === checkName).map({code} => code).join('<br/>');
$('#someElement').append(codes);
答案 1 :(得分:1)
小助手可能会有所帮助:
function asyncForEach(arr, cb, done) {
(function next(i) {
if(i >= arr.length) {
if(done) done();
return;
}
cb(arr[i], i, arr);
setTimeout(next, 0, i + 1); // a small trick to defer actions
})(0);
}
或者为了优化它,您可以对结果进行分块,并且每1000次迭代只产生一次:
function asyncForEach(arr, cb, done) {
(function next(i) {
if(i >= arr.length) {
if(done) done();
return;
}
let stop = i + 1000;
setTimeout(next, 0, stop); // a small trick to defer actions
while(i < arr.length && i < stop)
cb(arr[i], i++, arr);
})(0);
}
在你的情况下可以这样使用:
asyncForEach(myArray, function(el) {
if (el.name === checkName){
$("#someElement").append(`${el.code} <br />`);
}
});
然而,这里最慢的部分可能是附加在dom上。如果你不想拥有&#34;现场进步&#34;将dom更新批量处理为单个调用可能很有用:
let result = "";
asyncForEach(myArray, function(el) {
if (el.name === checkName){
result += `${el.code} <br />`;
}
}, function() {
$("#someElement").append(result);
});
然后即使是同步变体也可能足够快:
let result = "";
for(const el of myArray) {
if(el.name === checkName)
result += `${el.code} <br />`;
}
$("#someElement").append(result);
答案 2 :(得分:0)
解决方案之一是与员工一起执行代码。
worker是使用构造函数(例如Worker())创建的对象,该构造函数运行命名的JavaScript文件 - 该文件包含将在工作线程中运行的代码;工作程序在另一个与当前窗口不同的全局上下文中运行。因此,使用窗口快捷方式获取Worker中的当前全局范围(而不是self)将返回错误。
所以,你不会使用主线程