Go-like channels in 10 lines of JavaScript
11–20 of 65 posts
Re: Go-like channels in 10 lines of JavaScript
#12Re: Go-like channels in 10 lines of JavaScript
#13But there is no concurrency in Javascript! So even after this exercise, the running function still has to finish before the next can start. This will only create actual concurrency when each of the actors are themselves doing pretty IO heavy things where they wait for external processes to finish. Otherwise, if you actually have compute heavy processes that should run in parallel you should use the node.js cluster pa…
Re: Go-like channels in 10 lines of JavaScript
#14generator functions exist, which is not even needed in this case, you could just pass a promise as an argument
Of course, you don't need a channel abstraction to do that. To me, channels are the most intuitive and self-contained way to solve the problem, so I wanted to use that model of concurrency in JS.
Re: Go-like channels in 10 lines of JavaScript
#15This is interesting. Correct me if I don't understand is this only concurrent with respect to IO is that right? If you run a IO operation or network call (fetch api) in those promises, those shall be concurrent with the CPU execution of your Javascript? I think async/await is a great primitive. I've been working on implementing a async/await switch statement based state machine* in Java for multithreaded async/await.…
I actually think async/await is a terrible primitive, and if you’re on Java, the approach of Project Loom is vastly superior (i.e. threads can be cheap so everything can just be synchronous again). I’ve no problem with library-level concepts like promises and futures but it feels very short sighted to put it into an actual language, it’s just noise.
8 years ago I wrote a npm package that turned code that looks like this:
tcp.send("syn", function(syn) {
console.log("received", syn);
tcp.send("syn-ack", function(synack) {
console.log("received", synack);
tcp.send("ack", function(ack) {
console.log("received", ack);
});
});
});
into this: seq([tcp, console], function(tcp, console) {
var syn = {}; var synack = {}; var ack = {};
tcp.send("syn", this(syn));
console.log("received %s", syn);
tcp.send("syn-ack", this(synack));
console.log("received %s", synack);
tcp.send("ack", this(ack));
console.log("received %s", ack);
});
it was never ready for production use, but it showed that synchronous code illusion can be created from callbacks.How would you prefer to write asynchronous code?
How does Loom handle resource starvation problem? If a thread puts a while (true) {} in there somewhere, can that thread be preempted away from that kernel thread?
Re: Go-like channels in 10 lines of JavaScript
#16But there is no concurrency in Javascript! So even after this exercise, the running function still has to finish before the next can start. This will only create actual concurrency when each of the actors are themselves doing pretty IO heavy things where they wait for external processes to finish. Otherwise, if you actually have compute heavy processes that should run in parallel you should use the node.js cluster pa…
Re: Go-like channels in 10 lines of JavaScript
#17But there is no concurrency in Javascript! So even after this exercise, the running function still has to finish before the next can start. This will only create actual concurrency when each of the actors are themselves doing pretty IO heavy things where they wait for external processes to finish. Otherwise, if you actually have compute heavy processes that should run in parallel you should use the node.js cluster pa…
Yes and no.
At the “ECMAScript”-level, JavaScript has no built-in concurrency, but every serious JavaScript implementation enables proper concurrency via the async primitives and the internal scheduling.
Put simply, if you know how to write async code properly, your JavaScript code can achieve high concurrency!
Re: Go-like channels in 10 lines of JavaScript
#18But there is no concurrency in Javascript! So even after this exercise, the running function still has to finish before the next can start. This will only create actual concurrency when each of the actors are themselves doing pretty IO heavy things where they wait for external processes to finish. Otherwise, if you actually have compute heavy processes that should run in parallel you should use the node.js cluster pa…
Promise.all([new Promise(t => setTimeout(t, 3000)), new Promise(t => setTimeout(t, 3000))]).then(() => console.log('done'))
You'll notice it prints `done` after 3 seconds, not after 6.It just happened to be executed one by one but the VM handles the switching for us.
What you're talking about is parallelism, which JavaScript indeed does lack and you'd use cluster or workers for that. That's when things happen at the same time, outsourced to different cores. This is what JavaScript cannot do (yet?).
Re: Go-like channels in 10 lines of JavaScript
#19 const manifest = await createAssetsManifest();
compileBrowser(manifest);
compileServer(manifest);
I am wondering if since the creation of async/await that the idea behind callbacks and async operations in general in Node has been forgotten.Not referring to the author or anyone in particular. Just a thought since these keywords might used so often by engineers new to Node that they might not have ever learned what came before?
Re: Go-like channels in 10 lines of JavaScript
#20This is interesting. Correct me if I don't understand is this only concurrent with respect to IO is that right? If you run a IO operation or network call (fetch api) in those promises, those shall be concurrent with the CPU execution of your Javascript? I think async/await is a great primitive. I've been working on implementing a async/await switch statement based state machine* in Java for multithreaded async/await.…
I actually think async/await is a terrible primitive, and if you’re on Java, the approach of Project Loom is vastly superior (i.e. threads can be cheap so everything can just be synchronous again). I’ve no problem with library-level concepts like promises and futures but it feels very short sighted to put it into an actual language, it’s just noise.
The worst part of Rust, too, is that async/await is tacked on— and it’s just a bad primitive to start with.
I have many more thoughts on this that I might like to blog about, but it can be improved by having a async runtime of some kind (we don’t call malloc a runtime, but it is— and you need something similar for ergonomic async) — to wit, the de facto pseudo-answer for this in Rust is tokio (which should just be promoted to the stdlib, at this point; the vast majority of async code depends on it’s particularities).
It’s also causes quote-unquote “function coloring problems” left, right, and center — which is also avoidable. Just for kicks, consider a language with “call-async”/“yield”. Tie that in with a runtime and this whole topic becomes much, much, cleaner. Async at the callsite! (This is the blog I’ve been meaning to write)