Reputation: 2859
For the most part, I understand how to wrap asynchronous and synchronous functions in a promise and the benefits and reasons for doing so. However, I don't understand something about how they are processed in the browser.
For example, if two synchronous functions are invoked in turn (two consecutive statements), the second does not commence until the first returns. If each synchronous function is instead wrapped in a promise and then invoked one after another (not one in the then
statement of the other but two consecutive statements), are the synchronous functions going to process concurrently now instead of in order?
I have a good reason for asking other than just interest in a hypothetical scenario. I'm working on an extension that opens a tabbed display within a single local HTML page. When the page is opened, the injected script opens the indexedDB database and kicks off a set of promises that retrieve the data for each tab and populate the various sections of each tab with the appropriate data. Placing these within a Promise.all
gives the impression that all of this work is taking place concurrently and populating the tabs as the data is retrieved, as opposed to populating each tab in succession.
Within a number of the individual promises(one promise per tab), when the transaction completes, synchronous functions are invoked to display the data in different sections of that tab. As coded now, the synchronous functions for display are invoked one after another in consecutive statements, such that the second section of the tab is populated only after the first completes and returns. The data has already been retrieved for all sections because the entire transaction has completed; so, the second function for display doesn't have to wait for the first to complete. If those display functions are wrapped in a promise and invoked as such, will the two sections of the tab be populated concurrently?
The transactions could be split such that there is one transaction per tab section, and the synchronous display functions will each commence as soon as their specific data has been retrieved; but, I'd like to keep one transaction per tab.
Either way, the loading process will be sufficient; but I'd like to understand whether or not, even if not perceptible to user, wrapping the display functions in promises will result in the concurrent population of the separate sections within a tab.
Perhaps, I'm just confused and, although promises and Promise.all
give the impression of concurrent processes, there really is no such thing in JavaScript and all that happens is that the asynchronous functions are processed in turn as their events complete. If so, wrapping synchronous functions in a promise, as described above, has no benefit in terms of speeding up the population of data in the sections of the tabs.
If that is correct, then the only way to increase the loading speed would be to split the transactions; and that would help only if one of the data retrieval steps within a transaction was taking longer than the others and delaying the completion of the transaction and the commencement of the functions displaying that data.
I apologize for the length of this question and if it is considered inappropriate because there is no code to review, I'll certainly have no issue in deleting it. But, if you can explain where I am wrong in my understanding I'd appreciate it. Thank you.
Upvotes: 0
Views: 70
Reputation: 27245
Javascript is single-threaded, so there's no concurrency within the javascript environment itself. Your synchronous section-populating functions will execute on a first-come, first-served basis.
When you invoke an asynchronous operation like a network request promise (or even a setTimeout
call), that execution is dispatched to be handled outside the javascript environment, out in kernel-land, where where it can run without blocking js execution and possibly run on a separate thread.
When it returns, the container (the browser) pushes the result back into synchronous javascript-land by adding the callback to a message queue. When the javascript call stack is empty, the event loop checks the message queue for pending callbacks. If it finds one it pushes it onto the call stack to be executed on the next execution loop.
Whichever section call comes back first will be executed first, and any other asynchronous calls that return will have to wait until the first one finishes before they run.
There's a really great article somewhere that explains how all of this works far better (and more authoritatively) than I can. I'll try to find it and update my answer with a link.
Update: This post explains it quite well.
Upvotes: 1