4

Sorry about the title but could not come up with anything really informative and concise.

My situation is that I am launching a setTimeout and I want it to be able to run in the middle of a JS function (it is used to get around the issue with injecting GM functions into the web page).

unsafeWindow.testG = function(key, dValue){
var rValue;
setTimeout(function(){rValue = GM_getValue(key, dValue);}, 0);
alert(rValue);
alert(rValue);
return(rValue);
}

In the three tests rValue is still undefined (which makes sense because JS is single threaded for the most part).

So I have 2 solutions I have thought of.

Favourite: Is there anyway to tell JS to sleep in the middle of a function and work on background stuff (like Timeouts)?

Other: Does anyone know when this timeout will be called? Maybe after this function execution but before whatever called it starts up again? In that case making rValue global would solve the issue (but make slightly messier coding).

Or will it wait until all JS is done executing? In that case I would possibly need another setTimeout to process the result.

Jonathon
  • 2,571
  • 5
  • 28
  • 49
  • 1
    I don't really understand what your *Other* solution/question is asking. And it would also help if you explained what this function of yours is trying to do - right it just looks like a no-op wrapper for `GM_getValue()`. And if your code is sleeping when you're doing stuff in the background then your background work becomes the only work being done and it's not really background anymore, is it? Clarification required on what you're trying to achieve here. The only suggestion I can make is to consider using a callback function. – no.good.at.coding May 28 '11 at 03:20
  • With regard to Other extended explanation: When will JS decide it is safe to hand off execution to setTimeout? Lets say I have something like `testG(); /*has setTimeout run yet?*/ for(var count = 0 ; count < 200000 ; count++){} /*how about now*/` And it is the only JS on the page (in addition to testG's declaration). Will JS only hand off execution after the last JS has run? – Jonathon May 28 '11 at 03:29
  • 1
    "depends". I would argue that is correct -- however, see my question: [Asynchronous timer event running synchronously (“buggy”) in Firefox 4?](http://stackoverflow.com/questions/6084410/asynchronous-timer-event-running-synchronously-buggy-in-firefox-4) In cases FF4 (and FF3) will put in an event-loop (where I would argue it is incorrect to do so; it is an implementation "detail"). The only two cases I know of are `alert` (e.g. Heisenburgs) and `XHR`. I am not sure if this is really a bug or "open" to interpretation. –  May 28 '11 at 03:31

2 Answers2

3

There is no way what you're asking for can be accompished. Until HTML5 is a wide spread standard, you can't do what you're asking without thinking asynchronously.

For example :

unsafeWindow.testG = function(key, dValue, callback){
   var rValue;
   setTimeout(function(){
      rValue = GM_getValue(key, dValue);
      callback(rValue);
   }, 0);
}

and call this with a callback :

unsafewindow.testG(key, dValue, function(rValue) {
   alert(rValue);
});
alert("foo");

For the last sippet, "foo" will be echoed before rValue, because testG will execute the timeout function only when the Javascript thread is available, or only when there's no other script running.

Yanick Rochon
  • 51,409
  • 25
  • 133
  • 214
2

To answer your first question, there is no 'sleep' function in JS. In fact, there is a site devoted to trying to create one: http://www.devcheater.com/ The conclusion: you cannot.

If what you'd like to do is make the rest of your code run later, you can put that code in a function and setTimeout().

Of course, the usual way to handle the sort of scenario you have set up is with callbacks. Since you're basically waiting for the thing in setTimeout to happen, you can have it call the rest of your code whenever it's done. For example:

var fartResult
function waitAMinuteThenFart (callback) {
  function fart () {
    fartResult = 'fart'
    callback(fartResult)
  }
  setTimeout(fart, 1000*60)
}
waitAMinuteThenFart(function (result) { alert(result) })
Tamzin Blake
  • 2,594
  • 20
  • 36