-1

I have hundreds of master JS scripts which look like this and which I may not modify:

> some code filling parameter1
var response1=callAjax(parameter1);
> some code using response1 and filling parameter2
var response2=callAjax(parameter2);
> etc ..

The callAjax function can be changed or re-written. It currently calls Ajax in synchronous mode - which is deprecated - so it needs to be overhauled. Blocking the UI during the execution of the master file is a requirement (these are banking and similar applications so the end user is not allowed to edit any input fields or click any button during the process - a screen veil can be shown).

How can I modify the callAjax function to use async mode and leave the master scripts (hundreds or thousands of them) un-changed ?

I looked at using Promises or async/await but cannot figure how to use these in order to return the ajax response to the master scripts. Same with adding some global variables used as semaphores. Again, breaking the master scripts into several functions for each call is not allowed. These are plain Javascript, no jQuery.

  • Show your callAjax function so we can see how exactly you are making your request – Dan D Jan 12 '18 at 03:46
  • 1
    No, you *must* edit that code to make it work asynchronous. But if you are looking for horrible UX anyway, why not just keep it synchronous? – Bergi Jan 12 '18 at 04:06

1 Answers1

2

How can I modify the callAjax function to use async mode and leave the master scripts (hundreds or thousands of them) un-changed ?

You can't. If you use asynchronous ajax, then you can't return the value from the function because the function will return BEFORE the value is available. You simply can't make an async operation into a synchronous function. For a lot more detail on returning asynchronous operations from a function, see How do I return the response from an asynchronous call?. You will see that all the available options involve calling a callback when the async value is done or returning a promise and using a callback with .then() on the promise to know when the value is done and what it is.

If your requirement is that you block the UI and that you can't change the calling code, then you have to stick with synchronous Javascript. No asynchronous operation will do either.

Otherwise, get rid of those requirements and write proper asynchronous calling code and don't block the UI in this way (you can protect the contents of the screen from editing or button presses during the ajax operation with different techniques).


So, my conclusion from the problem you've described is that you need to lift some of your current requirements because there is no solution that:

  1. Blocks the UI
  2. Uses only asynchronous Ajax
  3. Returns the ajax obtained value directly from callAjax()
  4. Does not change the calling code that calls callAjax()

You can't do all of those at once.

The forward moving design choice would be to return a promise from callAjax() and fix all the calling code that uses it to use that promise. For blocking the UI, you'd have to use some sort of UI protection (screen veil, you called it, or something like that).


My advice if you have a large body of code using this old synchronous ajax function is to create a new ajax function with a different name that returns a promise and deprecate use of the old one for any new code (make all new code use the new one). Then, as needed and guided by business goals, rewrite uses of the old function to use the new one one at a time. This will at least stop more code being written with the old, synchronous ajax code. And, it will give you an opportunity over time to convert code to the new interface as needed.


Note that the closest thing you could get to calling code that looks close to what you have (but still requires changes) would be using async/await (available in the ES7 specification or in transpilers). You'd return a promise from callAjax() and then, the caller can await the result:

// async function returns a promise
async function someFunction() {
    try {
        // some code filling parameter1
        var response1 = await callAjax2(parameter1);
        //  some code using response1 and filling parameter2
        var response2 = await callAjax2(parameter2);
        // etc...
    } catch(e) {
        // handle error here
    }
}

P.S. It looks like your current code doesn't have a good way to communicate back ajax errors.

jfriend00
  • 683,504
  • 96
  • 985
  • 979