2

I have this code that uses an inefficientProcess() that consumes plenty of memory:

My goal is to use some sort of setTimeout(function(){...},0) technique so the browser will not get stuck while executing the code.

How do I change the code so it will work with setTimeout?

function powerOfTwo(num) {
    inefficientProcess();
    if (num > 0) {
        return powerOfTwo(num-1)*2;
    } else {
        return 1;
    }
}

function inefficientProcess() {
    var sum;
    for (var i=0; i < 500000; i++) {
        sum+=10;
    }
}

powerOfTwo(1000);

My goal is ofcourse to learn how to avoid browser crush when executing heavy calculations.

Alon
  • 7,618
  • 18
  • 61
  • 99
  • So...you are asking how to break up the loop inside `inefficientProcess` so that it will only block for short periods? What is your question, exactly? – dgvid Feb 25 '13 at 18:24

3 Answers3

3

Javascript is single-threaded, and all your code is blocking. There is a new standard in HTML5, WebWorkers API, that will allow you to delegate your task to a different thread. You can then pass a callback function to be executed with the result.

https://developer.mozilla.org/en-US/docs/DOM/Using_web_workers

Simple example:

function powerOfTwo(num, callback) {
    var worker = new Worker('inneficient.js');
    worker.postMessage('runTask');
    worker.onmessage = function(event) {
        var num = event.data.result;
        var pow;
        if (num > 0) {
            pow = Multiply(num-1)*2;
        } else {
            pow = 1;
        }
        callback(pow);
    };    
}

powerOfTwo(1000, function(pow){
    console.log('the final result is ' + pow);
});

in inneficient.js you have something like:

//inneficient.js

function inefficientProcess() {
    var sum;
    for (var i=0; i < 500000; i++) {
        sum+=10;
    }
     postMessage({ "result": sum});
}

inefficientProcess();
André Alçada Padez
  • 10,987
  • 24
  • 67
  • 120
2

As was mentioned in Andre's answer, there's a new HTML5 standard that will allow you to set off a task on a different thread. Otherwise, you can call setTimeout with a time of 0 to allow the current execution path to finish (and perhaps some UI changes to render) before the inefficientProcess is called.

But whether you can use HTML5 or not, the powerOfTwo function has to be changed to be asynchronous - whoever calls it needs to provide a callback method that will be called when (a) a thread spun up via WebWorkers returns, or (b) the setTimeout method finishes.

Edited to add example:

function powerOfTwo(num, callback)
{
    setTimeout(function ()
    {
        inefficientProcess();
        if (num > 0)
            callback(Multiply(num-1)*2);
        else
            callback(1);
    }, 0);
}

function inefficientProcess() { ... }
Andy Magee
  • 226
  • 3
  • 10
  • can you show me an example? I really need some code to see in my eyes to figure out how to handle this issue – Alon Feb 25 '13 at 18:28
  • `function powerOfTwo(num, callback) { setTimeout(function () { inefficientProcess(); if (num > 0) { callback(Multiply(num-1)*2); } else { callback(1); } }, 0); } function inefficientProcess() { var sum; for (var i=0; i < 500000; i++) { sum+=10; } }` – Andy Magee Feb 25 '13 at 18:31
  • how do you trigger this function? powerOfTwo(100,WhatGoesHere) ? – Alon Feb 25 '13 at 18:47
  • Another function name goes in there. In Javascript a function is treated like any other object, so you can pass in the name of some other function to be used as a callback: `powerOfTwo(100,callbackFunctionName)`. Or you can pass in an anonymous function (like the function I passed into setTimeout in my example). – Andy Magee Feb 25 '13 at 18:50
0

The HTML element allows you to define when the JavaScript code in your page should start executing. The “async” and “defer” attributes were added to WebKit early September. Firefox has been supporting them quite a while already.

Saw that on this Site

JudgeProphet
  • 1,687
  • 3
  • 26
  • 44