Is there a correct way to 'yield' in the cooperative threading sense in javascript?
Asked Answered
B

2

8

I'm writing a ubiquity plugin the long function callback for an ajax query is blocking up the GUI Thread causing firefox to lock up.

The obvious solution seem to be to use some sort of deferred execution of (i.e we want to periodically add the carry out doing this query function to the end of the event queue and then allow other commands to be carried out.

The only way I can think of doing this is to use settimeout with a timeout of zero... is this is guaranteed to work, or is there a better way of doing this.

Bandog answered 20/9, 2009 at 21:31 Comment(1)
How are you doing the AJAX? If you're loading a script tag, that could be blocking (browser blocks until the script comes back).Parental
M
8

Using setTimeout with a very small timeout (0 or very nearly zero if you're feeling paranoid) is the only way to do this in a browser context. It works very well and is very reliable, but be sure to yield often enough but not too often, as it does take a while to come back to you ("a while" in a computer sense, of course; it's almost instantaneous [modulo other things you may be doing] in human terms).

Marchioness answered 20/9, 2009 at 21:48 Comment(2)
All modern browser implementations have clamped setTimeout to ~10ms (basically 10ms on all non-windows systems, where the timer resolution required to get <16ms timers has a significant power usage impact). So you don't really need to worry about to short a timeout.Semination
@olliej: That's outdated information (if it was correct in '09, but it wasn't my experience then, either). Browsers do much more sophisticated handling than that, depending on the origin of the setTimeout call. This was codified a couple of years ago in the HTML5 spec but as I say, vendors were already playing (disparate) games before then. Short version: If your code wasn't called by a timer, you can use 0, and modern browsers will get very near that.Marchioness
C
3

Make sure you are using an asynchronous request as a synchronous request blocks the browser (which would explain the GUI lock-up).

If this is not your problem, I think you want something like this task queue.

var queue = [];

queue.push(someTaskFunction);
queue.push(anotherTaskFunction);
// ...

var runQueue = (function () {
    var len = queue.length, task = 0;
    for (; task < len; task++) {
        yield queue[task]();
    }
}());

Call runQueue.next() to execute the next task. Wrap it in a try..catch statement as such:

try {
    runQueue.next();
} catch (e if (e instanceof StopIteration)) {}
Creeps answered 20/9, 2009 at 22:2 Comment(5)
Cool - I wasn't aware that generators had been added to javascript. Am I correct in understanding that other tasks can take a control whenever a function returns then?Bandog
Note that generators are relatively new to JavaScript and not necessarily broadly supported.Marchioness
Specifically, it's a Mozilla extension not yet supported anywhere else; it's not proposed for ECMAScript262-5. (There's a note about ‘yield’ and ‘let’ maybe becoming FutureReservedWords in a future version of the standard, which is a long way indeed from the feature being standardised.) You must also request JavaScript version 1.7+ in the MIME type to get the feature at all.Denisse
@Denisse I thought it was "language" attribute where JavaScript version number is to be specified.Ethiopian
To everyone commenting: The question's author said he's writing a Ubiquity script so he can use Mozilla JavaScript.Creeps

© 2022 - 2024 — McMap. All rights reserved.