Non-blocking Synchronous AJAX

Is there a way to perform a synchronous AJAX query that doesn't freeze the browser? In my opinion synchronous requests are a lot easier to work with in most cases, but the fact that they block other parts of the code from executing is a real killer. Is there a way to get synchronous AJAX without the negative side effects? (And yes, I realize that the term "Synchronous AJAX" is an oxymoron.)

Answers:

Answer

I'll provide an example of the bad side of effects of allowing such behavior.

Lets say you have this program:

<script>
var file = "foo.json";

function nullIt() {
    file = null;
}

function loadFile() {
    if (file != null) {
        synchronousLoad(file);//imagine the load takes 5 seconds
        alert("i just loaded: " + file);
    }
}

window.onload = loadFile;
</script>
<button onclick="nullIt()">click me</button>

The bad thing here-

  • while the synchronousLoad() is blocking for 5 seconds, the user clicks the button, and the event handler quickly runs to completion.
  • Now the file variable is null.
  • synchronousLoad() finishes and returns, letting execution resume on the next line of code
  • but file is now null, and the message output to the user is broken.

The real issue here you cannot reason about your code the same way anymore. Just because some fact was true on line 5, doesnt mean its still true on the very next line. This makes it very difficult to write an error free program.

Some programming languages support multithreading, and you have to deal with these issues, although you have tools to help deal with these problems. But, it's still a lot of extra effort on the programmers part.

Comparatively speaking, using callbacks to do asynchronous operations is ez-mode.

Answer

No. Synchronous is, by definition, blocking. Nothing can proceed until the process completes. That includes the rest of the UI in the web browser.

It's supposed to be asynchronous, so the best approach is to design the code to work asynchronously.

Answer

In the upcoming ECMAScript 2016 (ES7) standard, there is a new set of language keywords designed to do something very similar to what you seem to be looking for, called async and await.

These keywords don't allow "non-blocking synchronous AJAX", but they do allow you to write asynchronous code in a way that looks synchronous. Here's a quick example:

// Let's say you have an asynchronous function that you want to call in a synchronous
// style...
function delayedEval(delay, func) {
  // First, ensure that the function returns a Promise object. If it doesn't, wrap it with
  // another function that does.
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(func()), delay)
  })
  // For more on Promises, see https://goo.gl/uaoDuy (MDN link)
}

// Then, declare a function as asynchronous. This causes it to return a Promise that 
// resolves to its return value, instead of returning its return value directly.
async function delayedHello() {
  // Inside an async function, you can call other async functions like this, which looks
  // very much like a synchronous call (even though it isn't).
  let message = await delayedEval(1500, () => "Hello, world!")
  console.log(message)
}

// This returns (a Promise) immediately, but doesn't print "Hello, world!" until 1.5
// seconds later. (At which point it resolves the Promise.)
delayedHello()

Try in Babel

Basically, instead of "synchronous AJAX without the negative side effects", async and await get you asynchronous AJAX without all its negative side effects. (Messy code with lots of logic for handling callbacks.)

async and await are part of the "async functions" candidate recommendation in the ES7 standard.

Answer

I don't think it is possible. Instead of trying to use synchronous queries, you can use the asynchronous approach and use the AJAX done event.

Example using jQuery.ajax()

jQuery.ajax({
    url: "URL HERE",
    data: "whatever you are sending"
}).done(function (data) {
    // Do things with data
});

So, instead of using a synchronous request, you can use the Asynchronous request and just execute code AFTER the request has completed. So, it won't freeze your browser.

Answer

For the reasons outlined in the other answers here, there is no way to perform a synchronous AJAX call without blocking other events in the browser.

However, if code complexity is your primary reason for wanting to avoid asynchronous method calls, you may be interested in the Javascript cross-compiler streamline.js, which allows you to write asynchronous method calls as if they were synchronous, and get the same result as if you wrote the call asynchronously.

From the project's GitHub page:

streamline.js is a language tool to simplify asynchronous Javascript programming.

Instead of writing hairy code like:

function archiveOrders(date, cb) {
  db.connect(function(err, conn) {
    if (err) return cb(err);
    conn.query("select * from orders where date < ?", [date], function(err, orders) {
      if (err) return cb(err);
      helper.each(orders, function(order, next) {
        conn.execute("insert into archivedOrders ...", [order.id, ...], function(err) {
          if (err) return cb(err);
          conn.execute("delete from orders where id=?", [order.id], function(err) {
            if (err) return cb(err);
            next();
          });
        });
      }, function() {
        console.log("orders have been archived");
        cb();
      });
    });
  });
}

you write:

function archiveOrders(date, _) {
  var conn = db.connect(_);
  conn.query("select * from orders where date < ?", [date], _).forEach_(_, function(_, order) {
    conn.execute("insert into archivedOrders ...", [order.id, ...], _);
    conn.execute("delete from orders where id=?", [order.id], _);
  });
  console.log("orders have been archived");
}

and streamline transforms the code and takes care of the callbacks!

No control flow APIs to learn! You just have to follow a simple rule:

Replace all callbacks by an underscore and write your code as if all functions were synchronous.

For more information on streamline.js, read the blog post Asynchronous Javascript – the tale of Harry.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us Javascript

©2020 All rights reserved.