Live data from Hacker News

Go-like channels in 10 lines of JavaScript

pedrocattori.dev

31–40 of 65 posts

Re: Go-like channels in 10 lines of JavaScript

#31

Earlier quoted context omitted.

JavaScript does have concurrency! Try the following: 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…

Is that concurrency? The CPU is not switching between tasks; rather, it's scheduling 2 callbacks to fire after a 3000ms delay. If you could perform 2 tasks (e.g. console.log(Array(1e8).fill(0).map((a, i) => i)), and have both run to completion without a significant delay between the two tasks, that'd be impressively concurrent.

Concurrency is not parallelism:

- Concurrency is making overlapping progress on two or more tasks.

- Parallelism is making simultaneous progress on two or more tasks.

Concurrent tasks can run in parallel, but they can also run not in parallel and still make overlapping progress by either cooperative or preemptive scheduling. You can imagine that in some larger tasks you have these 3 second sleeps, but all tasks are able to make overlapping progress without blocking the other ones -- that's concurrency!

Re: Go-like channels in 10 lines of JavaScript

#32
post #6

But 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…

> But there is no concurrency in Javascript!

Javascript has concurrency (which async/await and promises are).

It doesn’t have parallelism at the language level (but see, e.g., the Web Workers API).

Re: Go-like channels in 10 lines of JavaScript

#33
post #6

But 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…

Or use a language that supports multi threading in some sensible manner..

You’re asking for low-level features. JS is a high-level language.

Re: Go-like channels in 10 lines of JavaScript

#34

Earlier quoted context omitted.

> But there is no concurrency in Javascript! 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!

No. All the JS code is still executing serially in the same event queue. This is a good thing, lean into the guarantees it provides.

Sorry, I think you’re misunderstanding.

Highly concurrent code need not execute in parallel. Concurrency enables parallelism; concurrency does NOT mandate parallelism.

On top of that, it actually is possible in JavaScript environments like Node.js to write code that can, in fact, run in parallel.

Re: Go-like channels in 10 lines of JavaScript

#35
It's a bit out of fashion, but same thing can be achieved without any extra code using a built-in EventEmitter:

    let channel = new EventEmitter()
    await Promise.all([
      compile.browser(channel),
      compile.server(channel)
    ])

    // in compile.browser
    channel.emit("manifest", assetsManifest)

    // in compile.server
    channel.once("manifest", (assetsManifest) => ... )
A new emitter is used each time, so the end result is the same. Curious to hear what others think.

Re: Go-like channels in 10 lines of JavaScript

#36
post #23

The real essence of Go channels is their ability to participate in the built-in select keyword. Of course, Go does not have access to any magic CPU instructions that make it something Go can uniquely do. But anything that wants to be "Go channels but in X" need to be implementing select, not a send operation. Send operations are easy. And a useful primitive! Way back in the day, Queue in Python was the way to communi…

JavaScript has Promise.race, which is effectively the same thing (from a set of Promises, return as soon as the first one resolves).

Re: Go-like channels in 10 lines of JavaScript

#37

Earlier quoted context omitted.

Or use a language that supports multi threading in some sensible manner..

You’re asking for low-level features. JS is a high-level language.

High level languages can have parallelism constructs. E.g., Ruby, in which threads have limited parallelism (only when running lower-level code that releases the GVL) has Ractors, which run Ruby code in parallel.

Re: Go-like channels in 10 lines of JavaScript

#38
post #23

The real essence of Go channels is their ability to participate in the built-in select keyword. Of course, Go does not have access to any magic CPU instructions that make it something Go can uniquely do. But anything that wants to be "Go channels but in X" need to be implementing select, not a send operation. Send operations are easy. And a useful primitive! Way back in the day, Queue in Python was the way to communi…

> The real essence of Go channels is their ability to participate in the built-in select keyword.

Select is similar to a function in plan 9's threading library[1] (which is part of the Go lineage) called alt(). To use it you stick it in a switch like so: switch(alt(alts)){}. Select{} is syntactic sugar for some alt like functionality. Of course the programmer is responsible for setting up the alt structure and the channels it contains. Overall its a great library and I love working with thread(2).

See this wonderful article on Go' history in code for comparisons between Go, Limbo, Plan 9 C and Alef: https://seh.dev/go-legacy/

[1] http://man.postnix.pw/9front/2/thread

Might as well add a link to the source (that 9front repo is outdated, don't touch it): https://github.com/mischief/9problems/tree/master/sys/src/li...

Re: Go-like channels in 10 lines of JavaScript

#39
post #23

The real essence of Go channels is their ability to participate in the built-in select keyword. Of course, Go does not have access to any magic CPU instructions that make it something Go can uniquely do. But anything that wants to be "Go channels but in X" need to be implementing select, not a send operation. Send operations are easy. And a useful primitive! Way back in the day, Queue in Python was the way to communi…

Additionally, the approach in the article doesn't support anything like unbuffered channels, which is the default (for good reason) in Go. Even for a first approximation, the return type of `write` needs to be `Promise`. So even the send operation is not quite right.
Post reply on HN