Search code examples
javascriptasynchronousdeferred-execution

Can assignments be deferred and execution of current block continue?


I have been given some educational literature explaining asynchronous happenings in JS...

Take the following example where, server1 is a different server to the one running the website and the getData() function will execute a complex SQL query and then return a large dataset:

var data = server1.getData();  
console.log(data);

We can be almost certain that the console will say undefined. This is because the 2nd line of code will be executed before the result of getData() is returned.

My understanding is that the 2nd line will only be executed when then function has returned and its return value is assigned to data. If, indeed, getData() returns 'a large dataset', then by the time we get to the 2nd line data will be, 'a large dataset'.

Can assignment be deferred like this? I'm very familiar with async calls to remote servers and handling them through callbacks. But I believe that a simple function call in JS will return once (at most) and code is essentially executed single-threaded and sequentially executed.

Is this documentation somewhat misleading in its attempts to explain the pitfalls of asynchronous programming, however well intentioned?


Solution

  • The documentation could be either misleading, or a deliberate attempt to pose a situation that won't work in order to explain why it won't work... which I would call misleading anyway.

    JavaScript is single threaded - so any call out from the event queue must run to completion and return to the event queue (task manager) before another call out can begin.

     var data = server1.getData();  
     console.log(data);
    

    could return a large set of data, if and only if obtaining the data was requested as a synchronous operation, and further provided that the server "server1" allows cross origin requests (presuming "different server" means a different domain, protocol or port). Synchronous data requests are seriously discouraged as they stop the web page responding until the request is complete. If coded this way, the value of data would only be undefined it deliberately chosen as a value to indicate "no data available".

    The await operator introduced in ECMAScript 2017 can wait on a promise of an asynchronous result to become fulfilled, and delay assignment of the result to a variable. But usage such as

    var data = await server1.getData();
    console.log(data);`
    

    has restrictions that prevent its use in the example: it can only be used inside an async function, and async functions return a Promise object. So even if the server1.getData method were written as an async function, and internally used await to wait for data arrival, assign it to a variable and then return if from the function, the return value of an async function is not returned to its caller but used to fullfill the promise it returned when the call was actually made.

    server1.getData().then( data=>console.log(data)).catch(err=>console.error(err));
    

    is how the asynchronous operation might be coded to work if getData returns a promise. If called, call back functions provided by .then and .catch are called asynchronously, some time later. Meaning the code executing the above line can return to the event loop and let other things happen before the result of the query is sent back to the requesting web page.

    As for

    We can be almost certain that the console will say undefined.

    using the provided code? No. More likely in code for current (ECMA script version 6 or later compliant) browsers, we can be almost certain the console will say Promise { <state>: "pending" } or similar.