gpt4 book ai didi

javascript - JavaScript ES6 中大数据异步迭代的习惯用法

转载 作者:行者123 更新时间:2023-12-02 15:15:42 25 4
gpt4 key购买 nike

ES6 中是否有迭代大型数据集以避免浏览器超时的习惯用法?

假设我需要做一些事情,比如生成 1600 万个立方体之类的事情,并且直接循环会使浏览器超时。

function generateCubes(num) {
var cubes = [];
for (var ii = 0; ii < num; ++ii) {
cubes.push(generateCube());
}
return cubes;
}

var cubes = generateCubes(16000000);

所以我可以将其变成这样的异步回调

function generateCubes(num, callback) {
var maxPerIteration = 100000;
var cubes = [];

function makeMore() {
var count = Math.min(num, maxPerIteration);
for (var ii = 0; ii < count; ++ii) {
cubes.push(generateCube());
}
num -= count;
if (count) {
setTimeout(makeMore, 0);
} else {
callback(cubes);
}
}
makeMore();
}

但遗憾的是我突然不得不重组我的所有代码

generateCubes(16000000, function(cubes) {
...
// all the code that used to be after cubes = generateCubes
});

我可以将其转变为基于 promise 的东西,但这只会增加样板文件的数量。

无论哪种情况,我想我都可以编写一个通用版本

function generateThings(factory, num, callback) {
var maxPerIteration = 100000;
var things = [];

function makeMore() {
var count = Math.min(num, maxPerIteration);
for (var ii = 0; ii < count; ++ii) {
things.push(factory());
}
num -= count;
if (num) {
setTimeout(makeMore, 0);
} else {
callback(things);
}
}
makeMore();
}

在这个特殊情况下,我生成了 1600 万个东西,这是一种迭代。也许接下来我想迭代这些事情。

 function forEachAllThThings(things, op, callback) {
var maxPerIteration = 100000;
var num = things.length;

function doMore() {
var count = Math.min(num, maxPerIteration);
for (var ii = 0; ii < count; ++ii) {
op(things[ii]);
}
num -= count;
if (num) {
setTimeout(makeMore, 0);
} else {
callback();
}
}
doMore();
}

是否有一些更简洁或更通用的 ES6 方法可以做到这一点?

注意:请不要沉迷于生成多维数据集。这不是问题。此外,这不仅仅是超时问题,还可能是卡顿问题。例如,我曾经参与过一个需要反序列化场景图的项目。中等复杂的图形可能需要 5-10 秒才能反序列化(转换为对象)。在这 5 到 10 秒内,浏览器被卡住。

该解决方案与上面的 forEachAllTheThings 类似,我们每次只读取 N 个对象,以免锁定浏览器。这都是自定义代码。我只是想知道一些新的 ES6 功能是否提供了任何形式的简化来解决在多个 ticks 上进行大量工作的问题,就像它们似乎简化异步代码一样(就像在某种意义上是异步代码的一种形式)

<小时/>

更新

基于@Bergi关于 promise setTimeout的建议,我认为这就是建议。

// returns a Promise that resolves in `time` millisecond
function sleep(time) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, time);
});
}

// returns a promise that resolves to an array of things
function generateThings(factory, num) {
var maxPerIteration = 100000;
var things = [];

function makeMore() {
var count = Math.min(num, maxPerIteration);
for (var ii = 0; ii < count; ++ii) {
things.push(factory());
}
num -= count;
return num ? sleep(0).then(makeMore) : things;
}

// we need to start off with one promise
// incase num <= maxPerIteration
return Promise.resolve(makeMore());
}

function generateCube() {
return Math.random(); // could be anything
}

generateThings(generateCube, 300000)
.then(function(things) {
console.log(things.length);
});

我认为这有点 ES6 化,并且假设您的代码中已经有了 sleep (这似乎是一个合理的假设),并且会少几行。

最佳答案

我可能会将立方体的生成卸载到 web worker ,这不会有超时问题,假设多维数据集仅包含 JavaScript 基本类型,因此可以在准备好时发布到主 UI 线程。理想情况下,立方体为 transferrable objects因此您不必克隆它们,而是将它们从工作线程传输到主 UI 线程。

关于javascript - JavaScript ES6 中大数据异步迭代的习惯用法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34493048/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com