[英]idiom for async iteration over large data in JavaScript ES6
是否有慣用語在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功能是否提供某種形式的簡化,以解決它們似乎簡化異步代碼的方式(就某種意義上來說是一種異步代碼)的方式來解決在多個刻度上進行大量工作的問題)
基於@Bergi的建議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線程中。 理想情況下,多維數據集將是可轉移的對象,因此您不必克隆它們,而只需將它們從工作線程轉移到主UI線程即可。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.