4

There is a possibility that my code can defer two or more functions in short succession. Can I guarantee that each deferred function will execute in the order in which I created them? For my web application on iOS 5 & 6, the correctness of my code relies on deferred functions being executed in order.

I am using Prototype's defer, which is implemented using a timeout of 0.01 seconds.

A "deferred" function will not run immediately; rather, it will run as soon as the interpreter's call stack is empty.

From my own testing, it seems that they are executed in the order which I create them. The following did print out all the integers from 0 to 99 in order.

Test Code

for (var i = 0; i < 100; i++) {
    (function(x) {
        return function() {
            console.info(x);
        }
    })(i).defer();
}

Output

0
1
2
...
88
99

However, this result is not conclusive. I have no idea how it behaves with deeper functions or different CPU loads.

WojtekT
  • 4,735
  • 25
  • 37
Pwner
  • 3,714
  • 6
  • 41
  • 67
  • 1
    why not program as if there were no guarantee? – akonsu Apr 16 '13 at 20:10
  • in the `defer()` method it calls the `delay()` method which uses the native `setTimeout()`. Why not use custom event listeners? ie `document.observe('trigger:myfirstevent',function(){});` then `document.fire('trigger:myfirstevent');` as long as you defer the first call the rest of the calls will fire in order. (Custom events require namespacing using ":") – Geek Num 88 Apr 16 '13 at 20:28
  • @akonsu I discovered that iOS's JS event handling runs in a different thread than the main thread. In a multi-threaded environment, any function may be cut off halfway through and some other code gets executed. Interleaving code will cause state machine problems for those accustomed to JS's traditional single threaded engine. To alleviate these problems, I wanted to defer some event handling callbacks to simulate single-threaded code ordering. – Pwner Apr 16 '13 at 20:50
  • 2
    I think this question here has your answer: http://stackoverflow.com/questions/1776239/are-equal-timeouts-executed-in-order-in-javascript – Jeffery Grajkowski Apr 18 '13 at 15:59

1 Answers1

0

Prototype.js's defer() uses setTimeout() as its backing code.

function delay(timeout) {
    var __method = this, args = slice.call(arguments, 1);
    timeout = timeout * 1000;
    return window.setTimeout(function() {
            return __method.apply(__method, args);
    }, timeout);
}

//This calls Prototype's delay() function above (which calls setTimeout)
function defer() {
    var args = update([0.01], arguments);
    return this.delay.apply(this, args);
}

The spec for setTimeout says that order is guaranteed. However, a number of people have claimed that their functions were completed out of order so the different browsers might not all be implementing the spec properly. I'd assume the order is not guaranteed.

Instead, you should chain your functions. So, do something like:

var funcsToRun = [];
var currFunc = 0;

//Add the functions
for ( var i = 0; i < 100; i++ )
{ 
    funcsToRun.push( function(x) {
        return function() {
            console.info(x);
        }
    );
}

//This will chain the execution;
function chain() 
{
    //RUn current function
    funcsToRun[ currFunc ]( currFunc++ );

    //Now do next one if needed
    if ( currFunc < funcsToRun.length ) chain();
}

setTimeout( chain, 10 );
Don Rhummy
  • 24,730
  • 42
  • 175
  • 330