2

JavaScript uses asynchronous calls in most of the modern APIs dealing with "slow" things like disk IO and network. I realize what the purpose of this, however there are certain cases when making synchronous calls really needed.

For example, I have a JavaScript code that I can't rewrite. In the code there are synchronous call to a certain method. For some debugging purposes at developer's environment I want to intercept this call, send information to server and wait until server responds. This interceptor won't work on production. AFAIK, there was a way to do this with NPAPI, but now it is officially deprecated. And both Google Chrome and Mozilla Firefox provide only asynchronous socket API, so I have no chance to perform such interception. Another way is to send syncrhonous XMLHttpRequest, but is is considerably slow, at is requires HTTP connection and HTTP payload, so I would prefer WebSocket.

I have another corner case where I have to call IndexedDB, but it is very hard to explain. Unfortunately IndexedDB sync API is not implemented anywhere.

Are there another hacks to call asynchronous methods synchronously? I would accept browser-specific hacks, browser add-ons, plugins and so forth. Or may be someone knows how to ask all those committees (and browser developers as well) that develop Web standards to include at least WebWorker versions of syncrhonous API?

I know, that questions about calling asynchronous method synchronously were asked many times, and the common answer is "this is a bad idea". I realize that generally it is a bad idea, but in a certain cases we really need freedom to call synchronously.

Alexey Andreev
  • 1,980
  • 2
  • 17
  • 29
  • It's actually fairly easy, just do a while loop that completely locks the thread while the async function is running, and you've created a synchronous function. Actually implenting it with all sorts of async methods is probably going to be harder, and you generally shouldn't be doing this at all, as not being able to use the asynchronous methods is not the language failing to provide you with what you need, it's you that is failing to use the asynchronous methods as intended. – adeneo May 23 '14 at 16:57
  • @adeneo, I think that this empty `while` loop will boost CPU. And I'm not failing to use asynchronous methods, because I even have not access to code to be rewritten. Also rewriting code in async style makes program much slower, as we tear the original CFG, liveness information, and that spoils loop invariant motion, register allocation and other useful optimizations. – Alexey Andreev May 23 '14 at 17:28
  • Not sure you're getting it, there is only one thread and synchronous operations halt that thread, and subsequently the browser, the way to make asynchronous code synchronous is to just halt the thread until the callback executes, that way no other code can execute until the async stuff has completed. However you should *never* have to do this, and that's where your logic fails, there is ***no good*** reason to make async code synchronous. – adeneo May 23 '14 at 17:42
  • I am confused by what you mean when you say asynchronous and synchronous. Asynchronous calls work by making an HTTP request and then executing a function upon response...via promises. Synchronous calls work with message passing and listeners. Do you mean you're using a third-party API and it is making asynchronous calls, but you want to make them synchronously? If that's the case you can just rewrite their methods. – Anthony Shull May 23 '14 at 17:48
  • 2
    @AnthonyShull - Anything with a callback is generally async, such as setTimeout, HTML5 geolocation, webworkers, sockets, and yes, ajax. – adeneo May 23 '14 at 17:51
  • @AnthonyShull: Although HTTP requests are often asynchronous, they are not always so. Nor are they the only asynchronous operations around. I think you're misunderstanding the notions a bit. Synchronous programming is a style where the steps of your program proceed one after another without anything in between (or appear to from your perspective; the operating system may be doing plenty of other things.) Asynchronous programming is when your program suspends control and picks it back up after something has happened, such as an HTTP response, a GUI event, or a timeout completion. – Scott Sauyet May 23 '14 at 17:57
  • @adeneo that won't even work. The event machine will wait for the infinite loop to finish before calling the result callback. The infinite loop has no means of checking when it should stop waiting. – John Dvorak May 23 '14 at 18:20
  • @JanDvorak - I know, when halting the thread there's no way to get the result from the async callback, I was actually assuming that someone would figure that out *much* sooner, and we could all agree that there is no way to make async code sync (until ES6 is available with coroutines), and one should never have to do this either, as once again this is the developer failing to take advantage of async code. – adeneo May 23 '14 at 18:43
  • @JanDvorak - There is however one epic answer posted to this question `"I usually describe asynchronous code as viral: it quickly infects the code around it"` <- that statement can be summed up in pretty much two words "Developer Failure". – adeneo May 23 '14 at 18:45
  • @adeneo, please, read carefully my question. I'm not going to use this approach on production. It would be a hack for some debugging reasons. I don't want to start a holy war, but you don't try to convince me that I'm a bad developer and I don't understand syncrhonousity. People used processes and threads for more than 30 years, and they didn't need all this "asynchronousity". JavaScript now has the WebWorkers, so why does not it provide syncronous APIs? – Alexey Andreev May 23 '14 at 19:03
  • 1
    @adeneo: Perhaps you have a way around that issue, but I've never seen any simple way of turning code that requires the result of an asynchronous call into something synchronous. The big issue is when you try to turn something that relied on the results of a synchronous call into something that now needs the results of an asynchronous call. That "something" itself becomes asynchronous, as does anything that relies on it. If you have a way around this that doesn't smack of Developer Failure, I'd love to hear it! – Scott Sauyet May 23 '14 at 19:18
  • @ScottSauyet - There is no good way around it, and there generally is no need to create a way around it at all, and that's why there are no good examples of how to do it. ECMA 6 (the next standard for JS) will introduce coroutines, and then there will be a way to deal with this, but it probably won't be used much as it's not a very good idea. – adeneo May 23 '14 at 19:29

2 Answers2

2

I don't know of any way. I usually describe asynchronous code as viral: it quickly infects the code around it with more asynchronicity. I don't know any way to break that, and it seems unlikely to me that there is a way. Obviously there are techniques to make your asynchronous code look more synchronous, starting with Promises, and continuing into macros and such. But in the end, the runtime is still asynchronous.

Maybe someone smarter than me can provide an interesting suggestion. I'd love to hear it too, although I don't have any personal need at the moment.

Scott Sauyet
  • 49,207
  • 4
  • 49
  • 103
1

Some other ideas that you might want to consider:

For the web based traffic

Use a proxy server to intercept the communication. I found an article here that discusses using a proxy server with web sockets. A properly written proxy could hold onto the transferred data until its exchange with the server was complete, then pass things forward.

For the IndexedDb

You could create a wrapper function around the IndexedDb calls, or at least the ones you needed, that would allow you to interject whatever behavior you needed in. This wrapper could modify data and perform its own async business before invoking the callback method.

Community
  • 1
  • 1
Jeremy J Starcher
  • 23,369
  • 6
  • 54
  • 74
  • How proxy server would help me to avoid asyncrhonous call on client? How can I write wrapper for IndexedDB, that behaves syncrhonously? – Alexey Andreev May 23 '14 at 17:29
  • The proxy server wouldn't help you avoid the async call on the client, but -- depending on your use case -- remove the need to avoid the async call. As for the `IndexDb` according to the Mozilla docs, there is no browser that supports the sync calls yet: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API – Jeremy J Starcher May 23 '14 at 17:45
  • 1
    @AlexeyAndreev the idea, if I understand correctly, is to use a proxy to turn arbitrary calls into XHR calls, which you can do synchronously using the standard XHR API if you really need to. And you can't really avoid the performance penalty of synchronous waiting for network calls anyways. Websockets can save you a round-trip for a TCP handshake, but the browser should be using persistent connections even for XHR anyways. You can't avoid the round-trip of actual data no matter what connection type you use. – John Dvorak May 23 '14 at 17:58