最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to deal with heavy-load processing of displayed data in the browser - Stack Overflow

programmeradmin2浏览0评论

The context

  • We have an Ember-based app which handles large amount of structured data (Business process models).
  • Important! We would really like to keep our app offline-able, as far as possible.

The need

While we only have to display these data, edit them, and so on, there is no show-stopper in the radar...

But now, we want to apply processing on these models: validity checking, paths finding... and several kind of time/memory consuming algorithms.

The problem

We could process algorithms on the server, but that would kill the app's offline mode.

We have thought about web workers to avoid freezing application and process algorithms in the background, but we faced a major issue: data duplication when passing the data to the worker. Using Transferable Objects would make the app lose the ownership (and the data) during at least the putation, so it does not seem viable.

How would you handle this problem? Is our only way out the use of a "coroutine-like" implementation of our algorithms? Any clue?

The context

  • We have an Ember-based app which handles large amount of structured data (Business process models).
  • Important! We would really like to keep our app offline-able, as far as possible.

The need

While we only have to display these data, edit them, and so on, there is no show-stopper in the radar...

But now, we want to apply processing on these models: validity checking, paths finding... and several kind of time/memory consuming algorithms.

The problem

We could process algorithms on the server, but that would kill the app's offline mode.

We have thought about web workers to avoid freezing application and process algorithms in the background, but we faced a major issue: data duplication when passing the data to the worker. Using Transferable Objects would make the app lose the ownership (and the data) during at least the putation, so it does not seem viable.

How would you handle this problem? Is our only way out the use of a "coroutine-like" implementation of our algorithms? Any clue?

Share Improve this question asked Jun 28, 2012 at 15:41 Mike AskiMike Aski 9,2364 gold badges47 silver badges66 bronze badges 4
  • I think the important question is whether you can afford not to freeze the app. Assume the user makes changes to the data while the algorithm is running. Will the results of the process running in the background still be valid/relevant? If not, it's probably best to show the user a progress bar and proceed with the putations. – Qnan Commented Jun 28, 2012 at 17:24
  • What is the problem with data duplication? Too much stuff to serialize to the worker? – Simone Gianni Commented Jun 28, 2012 at 23:46
  • @SimoneGianni The main issue is data synchronization between UI context & worker context – Mike Aski Commented Jun 29, 2012 at 6:36
  • @MikhailKozhevnikov There is no way to frozen UI, even with progress bar... – Mike Aski Commented Jun 29, 2012 at 6:38
Add a ment  | 

2 Answers 2

Reset to default 6

If your major concern is not to freeze UI during lengthy javascript processing you developed, you can refactor loop bodies into sequential steps, such that each step call its next by using window.setTimeout. This technique allows the (single) thread to process UI events between each interaction:

var pr = function(x) {console.log(x)};
var COUNT=3;

// original regular javascript loop
for(var i=0; i<COUNT; i++) {
  var msg = "current index is (" + i + ")";
  pr(msg);
}

// step-by-step sequential calls
var body = function(i) {
  var msg = "non-blocking for: index is (" + i + ")";
  pr(msg);
}
nonBlockingFor(body, 4);

The function nonBlockingFor calls the first argument (as a function) the number of times passed as second argument. It's definition follows:

// function constructor
var nonBlockingFor = (function() {
  function _run(context) {
    if(context.idx > context.max) return;
    context.fnc(context.idx++);
    window.setTimeout((function(){ _run(context)}), 1);
  }
  return (function _start(ufn, uqt, runId) {
    _run({idx: 0, max: uqt -1, fnc: ufn || (function(){}), runId: runId});
  });
})();

Please note that this is a very simplified function and it can be improved to handle other multi-thread related issues -- i.e: waiting for the threads to finish (join). I hope this code helps you. Please let me know if you like this approach to the problem, I could spend some time improving my suggestion, if you like.

Long time has passed, but still : a solution may be http://jscex.info/

Javascript is single threaded in nature, and it's a design choice cause multithreading is a hard topic 99% of the casual javascript developers would not handle properly.

Workers are the only way to obtain another thread and not block the UI, but to make them usable without the dangerous side effects of real multithreading, they run in a pletely separated context, as you noticed. So they are more similar to calling an external mand passing mand line parameters than spawning another thread.

So, working in "async" mode is the only solution right now, but since you are not waiting for a click of a button or a remote connection to plete, the only async event you can bind to is the tick of a timer, which leads to the poor code style that plagues long running operations in js.

There is however a small library, that I found to be very interesting and quite unknown, that (despite it's poor website) is able to "convert" on the fly a beautifully written procedural code to the mess of timers and functions the async model inherently requires : http://jscex.info/

As in windows 3.1, you just need to "yield" ( $await(Jscex.Async.sleep(50)); ) some time to the browser so that it does not pletely freeze. It will actually freeze under the hood, but if you yield frequently enough no one will ever notice :) (afterall, that is how multitasking still works inside each single core of your cpu, very small slices of time during which the CPU is 100% working on a single set of instructions .. take that to 20 ms an no one can tell).

I think that could help you "produce" a coroutine-like JS without actually "writing" such code, but delegating to a "prepiler" the work of messing it up.

发布评论

评论列表(0)

  1. 暂无评论