原文: https://www.quora.com/How-does-a-single-thread-handle-asynchronous-code-in-JavaScript
--------------------------------------------------------------------------------
Well, arguably its not true that Javascript is single threaded if you see from the under hood working of browser JS to your JS code, there are thread pools. By single threaded what they mean(browser end) is your JS runs into a single threaded event loop. There is one single thread that handles your event loop. Under your JS, the browser code is running multiple threads to capture events and trigger handlers, when they capture any new event, they push it on an event queue and then that event loop, in which your code is running gets triggered and it handles the request e.g. It performs an action which can be to show a DIV, which again triggers the Browser to print it, which in turn runs a thread to do it(from the thread pool).
Lets take an example of your JS algo.
window.onload
Show Header
Send an Ajax Req. for config - > When done, alert a box
Do some more page animations
So when you told the browser to send an ajax request with a provided callback, it saves it in memory and this Network IO call is transferred to a thread in Network Pool Threads, your code next to that line will continue to work. After the Network Call thread has done its job, it will push on the event queue the response. Remember that event loop? Here is when it comes to action, it picks the top entity and then trigger your callback(Context Switching on CPU Level), which in turn could be anything. Now try doing something like this.
window.onload
Show Header
Send an Ajax req. for config ->
When done -> Trigger another Ajax
-> for loop 0.100000000
Do more animation
Now here, if even your second Ajax completes in due time, its callback will not be triggered until your for loop exits. Its a sort of blocking within the thread, none of the event will be fired and everything will be frozen!
Hope that clears your doubt.
Cheers!
-----------------------------------------------------------------------------------------------------------------------
Javscript is single-threaded. Each browser window has only one Javascript thread running inside them. What makes the asynchronous events possible is the browser’s Event Loop and the associated Event Queue.
Suppose Javascript engine is running some function, and in the meantime, user clicks on a button on the webpage. A Key Press event would be fired and since Javascript engine is busy doing some other work, this event would be queued in the Event Queue.
Javascript handling the Event Queue would look something like
- while (waitForMessage()) {
- processMessage();
- }
waitForMessage() waits for a message synchronously in the queue and when it gets one, it processes that message.
In the example above, after Javascript engine finishes executing that function, it checks for the next message in the queue. It sees that some Key Press event was fired while it was busy doing some other work. So, it handles that Key Press event either by calling any callbacks that may be bind to that key press event or doing some thing else.
But all of this happens so fast, that it feels like every thing is running parallely. But in reality, all of this is just a simple queue managed by a single thread running a infinite loop.
For information about how threads work in general , you can checkout this article.
----------------------------------------------------------------------------------------------------------
You can look at the presentation at Introduction to Node js.
Though it is in context of NodeJS but the basics remain the same.
The JS runtime i.e. V8 is same in case of browser (Chrome) and Node.
Slide 12 talks about Single Threaded nature.
Slide 13-16 talk about other properties of JS like non-blocking, event driven etc.
Image on Slide 17 talks about the event loop Dron Rathore is talking about.
Analogy of working style of JS with the real word 'King and Servants' on slide 18 helps a lot understanding it as a whole.
Hope this helps.
-----------------------------------------------------------------------------------------------------------
You may have noticed that in JavaScript code every function you write returns without waiting. You never write JavaScript code that looks like this:
- while (true) {
- API.blockingCall()
- }
One consequence of this is that all the functions you write return to their caller as soon as they have done their thing. All the functions that call functions you write do the same thing. Ultimately, they return to the dispatcher of the single-threaded event loop. The dispatcher dequeues the next event from the event queue, identifies the function to call to handle that event and the process continues - no function ever blocks, which means every function returns to its caller in a short period of time.
So, this is how your call back function gets invoked. The function you wrote that registered the callback - and the the functions that called it - return to their caller. Then, and only then, and only if the AJAX request is complete or has failed, does the function which implements your callback get called, but only when the dispatcher in the single-threaded event loop reaches the event that will cause that function to be invoked.
There is no magic here - no interrupting code to service a response. It is just the event loop dispatcher spinning through its queue of events, one at a time, calling functions on a single thread.
To make your mental picture complete, you need to imagine these unseen things:
* a queue of unprocessed events
* a loop that iterates through the queue of unprocessed events one at a time, and invokes the event handler function for those events.
* a mechanism that allows the result of an AJAX call to be enqueued on the queue of unprocessed events.