That seems like a dangerous, misleading statement.
setTimeout(() => {
var x;
while (x < 2000000) {
x += 1;
}
});will block. Event listeners, timeouts, and xhr requests just wait to receive a response. They're not actually doing anything while that happens. And their callbacks basically just become 'synchronous' when they get that response.
But since the language is single-threaded (or at least, it defines nothing about multiple threads with shared memory), there is a strong incentive not to have blocking functions.
But it is interesting that it doesn't mention the oft repeated meme "JavaScript is single-threaded". Would be nice with an example showing parallel number-crunching without WebWorkers. Is that possible?
Lately, I've been playing with libev and thread-pools together in Nim; so you write async/await stuff everywhere with futures, including number crunching, which gets delegated out to the thread pool and yields back to your main thread when it's done. It's quite nice, but I forgot how complex this stuff gets!
Not quite, since using threads internally (thread per IO operation) would defeat a purpose of async system, which is created specifically to not pay threading cost (context switches, etc.). In layman terms, kernel will simply invoke your C callback function when "stuff happens", and libuv propagates that to JS in platform-agnostic manner.
There are still threads and thread pools in V8 and node for stuff like calculating PI (or, more realistically, password hashing and other number crunching), but that is mostly unrelated to async IO itself.
Some google queries: select, poll, epoll, kqueue…
Single-threaded is desired behavior in the case of web ui and of Node, which is multi-process c/++ under the hood and JS responding to message queues.
It's pretty simple. Functions block. The messaging queue that triggers function calls in event-driven, setTimeout, XHR, talking to another JS runtime cases doesn't. So yes, you have to be careful to not lock up your entire server by processing images with JS function calls in the same runtime.
But the huge benefit you get out of this tradeoff is that you don't ever have to worry about two things trying to change something at the same time. Everybody is locked until your functions are finished and with async that doesn't typically take very long.
The synchronous lib calls in Node are mostly for convenience. I use them all the time when doing simple file I/O stuff where I just want to read something from a file, do something to it and stick it in a var or a new file. In a server or more complex application, however, you always want to use async callbacks.
Generators and yield for some types of crunching. Not parallel, but at least not a tight spinning loop.
You can fake it by kicking off multiple executions on a data set and chunk the work load across the data set, so they progress incrementally and equivalently. The data might be small enough (or browser fast enough) to give the impression of things being done in parallel.
It's a somewhat "new" feature of JavaScript but most modern browsers already implement it[2].
[1] https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers...
The event loop architecture is also heavily used in iOS / Cocoa, although it is often not well understood by developper. Each thread has an event loop, including the main UI thread, and many weird behaviors can be understood better once you know a bit about them.
Which made me wonder if a simple implementation of agent based concurrency in swift server couldn't simply be one agent - one event loop, plus a way to prevent direct calls across agent boundaries. Server is not iOS, but i suppose some language facilities should already be there and make it easier to implement.
/side topic
https://jakearchibald.com/2015/tasks-microtasks-queues-and-s...
http://www.c-sharpcorner.com/article/overview-of-micro-tasks...
Firefox 53 produced a log that matched what I expected but then I ran it a few more times and then it happened in another order which I then read was the order they were supposed to appear.
>Microsoft Edge, Firefox 40, iOS Safari and desktop Safari 8.0.8 log setTimeout before promise1 and promise2 - although it appears to be a race condition. This is really weird, as Firefox 39 and Safari 8.0.7 get it consistently right.
So Firefox 39 may have gotten it consistently right on his machine, Firefox 40 did not on his machine and Firefox 53 still does not on my machine.
What I would like to find is _why_ do they work like this. What is so important that this is the way it must be done. We live with browsers that lock up for a while until they figure out that some code has inadvertantly done a while(true). Promises and similar callback amelioration techniques took ages to turn up, when without the event model they might never have been required at all. Is there a reason for this? Is it a good reason?
The history of JavaScript is that it started as a sort of "quick and dirty" scripting language at Netscape. Creating a completely separate event model wasn't possible in those circumstances, so JavaScript ended up being shaped by the single-threaded lowest common denominator of Win32 and other platforms that Netscape ran on.
As the UI uses the same thread as JS, if JS blocks, this would lock up the whole window (clicking on things would do nothing), so it's important functions don't take too long or suspend the thread.
There was an experiment within servo to see if rendering and JS could run in separate threads entirely, but I'm not sure how that went? https://github.com/servo/servo/wiki/Design
You also don't gain a lot from multithreading in typical UI event handling. Most event handlers have to finish quickly anyway or the user will notice lag in updating the display. A UI that responds to events slowly and out of order would confuse users, even if it had no concurrency bugs (which is unlikely).
If the article had used I/O (http request) as an example of event handling (message queuing), it would have added some concurrency context.
To gracefully establish expectation in the user - A processing indicator will buy the application some time before the user gets impatient. The setTimeout 0 pattern is useful to delay the long running process enough for the browser to redraw the UI to throw up the processing indicator.
One can further achieve another state in the processing indicator by leveraging time delayed CSS animation which runs in a thread that's parallel to JS. So you could use CSS to augment the content of the processing dialog while the blocking JS is running.