使用JS/JQuery异步迭代大型对象数组

我有一个从JSON文件读取的大型(约10,000项)对象对象,并将其存储为局部变量,格式如下:

{
    "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完成此操作?


解决方案

这里有个小帮手可能会有帮助:

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。如果您不想有"实时进度",最好将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);

相关文章