Fork me on GitHub
#clojurescript
<
2022-04-29
>
pinkfrog05:04:31

In Clojure, I can use java.util.concurrent.CyclicBarrier to achieve the purpose of only continuing when all the dependent tasks have finished. How can I achieve the same purpose in Clojurescript / JS land?

pinkfrog05:04:06

A typical example would be, when we start a system, first start all subsystems, and continue only when all subsystems have finished starting.

p-himik05:04:56

Given that JS is inherently single-threaded, there are two options: • Run all tasks sequentially • Run them asynchronously and then use Promise.all.

☝️ 1
pinkfrog05:04:26

The issue is one task invokes an async function.

pinkfrog05:04:36

So Run all tasks sequentially goes out of the way.

pinkfrog05:04:18

My first plan was go with Run all tasks sequentially , but seems there is no way for a non-async function to wait for the completion of an asynchronous function.

pinkfrog05:04:46

For Run them asynchronously and then use Promise.all`` Not sure returning a promise from task fits in the cljs world.

p-himik05:04:29

CLJS world is full of interop, so I'd consider it fine. :) Especially given that one task already involves an async fn - assuming we're talking about native JS async capabilities and not core.async, you're already using promises, albeit potentially implicitly. If you're already using core.async elsewhere and if you really want to avoid promise interop, then you can use core.async as well.

pinkfrog05:04:44

Sounds like the core.async approach is a little bit verbose to implement. Each task could return a close-ch, and we have a goroutine that checks each close-ch has closed and then continue.

p-himik05:04:37

If 9 out of 10 tasks are synchronous, then just run them synchronously but in the same go block. You don't need to make them all async.

p-himik05:04:12

(go
  (task1)
  (task2)
  (<! (task3))
  (start-system))

didibus05:04:42

JS is colored, so if you use anything async, everything all the way back to the entry point has to be async as well.

didibus05:04:58

That's true even if you use core.async.

didibus05:04:48

You'll have to pick what async construct you want to use, JS native promises or core.async channels are the two best choices.

didibus06:04:04

One option is to have async tasks return promises, and then use Promise.all or Promise.then. The other option is to have the async tasks return a channel, and use (a/map vector tasks) to wait for them all, or just use (go (<! task1) (<! task2))

👍 1