0

this may be a stupid question, but....is there a way in Javascript to synchronously wait for a specific request to finish without locking the browser thread?

The goal is to call server-side using ajax and executing piece of code after the call is finished AND avoiding callback (hell). Some simple piece of code like this.

// some js code
var result = doServerCall(); // w/out (b)locking the browser thread -> browser must remain responsive
// some js code to process the result

Please note setTimeout and setInterval is not acceptable solution, what is needed is straightforward execution as above. Eventually a callback after which the execution would continue at the point where the call to server has been done is also ok (see below).

I was using the following in a Firefox Add-on (which is not exactly the thing i want, but is still an acceptable solution).

globalDone = false;
// some js code
doServerCall(); // asynchrnonous call here, the callback is below
var thread = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager).currentThread;
while ( globalDone === false ) {
    thread.processNextEvent(true);
}
// some js code to process the result

the callback

function processResponse ( xhrResponse ) {
   globalResult = xhrResponse;
   globalDone = true;
}

Going through the Internet, StackOverflow and forums everybody seems to want this, yet no browser looks to implement it

BennyHilarious
  • 373
  • 3
  • 15
  • Any explanation for the downvote? – BennyHilarious Feb 22 '15 at 18:29
  • 1
    In theory, you can make a synchronous ajax request using a Webworker, without locking the browser. But to send the results back to main thread (via `postmessage`) would be asynchronous. – levi Feb 22 '15 at 18:46
  • 1
    Also, this may be of interest - http://davidwalsh.name/async-generators – levi Feb 22 '15 at 18:52
  • @levi Thanks for your comment! I was trying to figure out a way to use a WebWorker for that (it is quite new i guess - Ecma Script 6?), but for some reason did not quite like it. Can you please post some snippet to an answer...if that looks ok, i will mark it as a correct answer. – BennyHilarious Feb 22 '15 at 19:08
  • 1
    Just to clarify, in Webworkers you cannot access the DOM. So if your intentions are to immediately update the DOM with ajax results, then it wont be much different from using async ajax, since the communication of ajax results to main thread is asynchronous. – levi Feb 22 '15 at 19:15
  • @levi I think i will give the WebWorker a try. You can do synchronous requests (with browser UI not blocked) with it and the unavailability of DOM can be hopefully handled by passing the message to the "main" thread via the postMessage. Many thanks Levi..it seems that ES6 and you finally solved my long-lasting issue :) If you don't mind creating an answer from your comment, i will mark it as correct. And thanks for the second comment regarding the generator function! – BennyHilarious Feb 22 '15 at 19:25

2 Answers2

2

this may be a stupid question, but....is there a way in Javascript to synchronously wait for a specific request to finish without locking the browser thread?

No, there's no way to do this with synchronous code. The whole purpose of asynchronous code and AJAX is to solve exactly this problem.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • The asynchronous way and AJAX is ok, but then your code must be built around callbacks. and that 's what i want to avoid. – BennyHilarious Feb 22 '15 at 18:25
  • Yes, of course that it should be built around callbacks. That's how asynchronous code works, contrary to synchronous and sequential code. If you don't want to be blocking the user's browser that's the proper way to write code in javascript. – Darin Dimitrov Feb 22 '15 at 18:25
  • Yet the second example does not block the browser, requires only the one callback i wrote (no other callbacks needed) and is sequential. So there seems to be a way to allow it in the browser (and e.g. mozilla does it for addons). So maybe the question shoud have been...why no browser supports synchronous sequential non-blocking requests.... – BennyHilarious Feb 22 '15 at 18:36
2

You can achieve synchronous HTTP requests, which do not block the UI thread, by making the request from a Webworker. However, communicating the results back to the UI thread, would still be asynchronous. Also, the start-up of a Webworker has time and memory costs, so keep that mind.

Another possibility is using ES6 Generators to simulate non-blocking synchronous execution of async functions. See here. However, browser support for this is still limited.

Webworker Example:

Worker

self.onmessage = function (event) {
    if (event.data === "init") {
        var xhr = new XMLHttpRequest();
        xhr.open("GET", "foo.com", false); // false means non-async
        xhr.send(null);
        var result = xhr.responseText;
        // do stuff with result...

        self.postMessage(result); // pass result
        self.close(); // terminate self
    }
};

Main script

var worker = new Worker("myWorker.js");
worker.onmessage = function (event) {
    console.log(event.data);
};
worker.postMessage("init");

Webworkers can also be utilized without needing a separate file, as described here.

Community
  • 1
  • 1
levi
  • 23,693
  • 18
  • 59
  • 73