簡體   English   中英

JavaScript ES6中用於大數據異步迭代的慣用法

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM