4 ms·
The whole point of abstractions is for us to not have to worry about the underlying complexity. If I want to program in a way that is close to how the hardware
by voidr 10y ago
The whole point of abstractions is for us to not have to worry about the underlying complexity. If I want to program in a way that is close to how the hardware works, I'll pick a language like C, however when I choose a high level language, I do not want to care if everything my processor performs is async.
What difference does it make if from the processor's perspective I have:
```js
somepoeration().then(function() {
// do stuff
});
```
or
```js
somepoeration();
// do stuff
```
In both cases my program will just wait for 'somepoeration' to complete before doing anything useful.
- colordrops 10y agoThat's not accurate. If you have any code after the line in the first example, it will be executed before the function in the "then" call. You could run several asynchronous operations (nearly) simultaneously. I/O will execute as fast as possible rather than wasting cycles running things sequentially.
- drawnwren 10y agoI'm fairly sure his point was that if he wanted code to execute between the calls he would rather write that in his code directly than deal with the cognitive overhead of reasoning about constant async calls. Async makes a lot of sense in cases where you are waiting for an event outside of your server's process, but async calls in the same code base seem a bit over the top.
- fsloth 10y ago"I do not want to care if everything my processor performs is async." The point is not the processor. The point is that all IO operations take time. Processing the IO operations concurrently with the serial program logic is where the beef is. Writing asynchoronous code in C or C++ is tedious to say the least in my experience, with weird concurrency bugs looming everywhere.
- bcoates 10y agoIn the second case, IO is not allowed to interrupt between between 'someoperation' and 'stuff' and change your program's state. In node, the first form is only needed when 'someoperation' has to perform IO to do its job so concurrent operations are unavoidable. If you're trying to reason about your program, this is huge. It very much matters where these points are. A concurrent thread being allowed to jump in and modify memory at any time at all, even halfway through a primitive math operation (the deranged C / Java / Python[1] memory model) means a correct program is a morass of locks and defensive programming and an obvious program is horribly broken. Communicating sequential processes (Go, PHP+MySql) makes IO have a modestly simpler synchronous syntax at the cost of communicating between I/O operations much more complex (sending a message to a port or performing some sort of transaction instead of just assigning to a value). It's a tradeoff. node.js does assume you're writing a network program that needs to overlap multiple communicating I/O operations; if this isn't the case there's no tradeoff to make and non-communicating sequential code is probably easier (think PHP without a database or sessioning) [1] Python is modestly less braindead by having a very modestly larger set of operations guaranteed to be protected by the GIL. Hoever, it's not composable at all and it doesn't really make reasoning about nontrivial programs easier in practice.
- majewsky 10y ago> A concurrent thread being allowed to jump in and modify memory at any time at all, even halfway through a primitive math operation (the deranged C / Java / Python[1] memory model) means a correct program is a morass of locks and defensive programming and an obvious program is horribly broken. This ignores that most threads, most of the time, operate on their private memory. When your request thread is querying the database and rendering some HTML based on the data from the database, then the only thing that needs to be guarded is the database access. The HTML rendering happens on thread-private data.
- cantagi 10y agoIf you're trying to reason about your program, this is huge. It very much matters where these points are. A concurrent thread being allowed to jump in and modify memory at any time at all, even halfway through a primitive math operation (the deranged C / Java / Python[1] memory model) means a correct program is a morass of locks and defensive programming and an obvious program is horribly broken. This can be solved by functional programming. Since the original article was written, JS has `const` and `let` [1] . Also, there are now numerous statically typed functional languages that compile/transpile into JS. Also, if a developer understands exactly how JS is executed, the problem is mitigated: var mutableState = {} asyncFunc.then(nextAsyncFunc) syncFunc() If you ignore web workers and node.js threading libraries people have written, Javascript always (by design) finishes executing synchronous code before executing any async handlers (your code is in a queue of handlers). This means that syncFunc will never be interrupted by nextAsyncFunc and have mutableState mutated during its execution. Of course, this means that if you do any intense computation synchronously inside a web server, it will block all other requests until it completes, and it will only use one core.
- posterboy 10y agoThe difference is that an async call takes a callback and the side effects of the callback, if any, are not immediately available. But anyway the second call may as well be synchronous and blocking.