question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Bring back IO#runAsync and friends?

See original GitHub issue

Nice to meet you!

I’m having a difficulty using Cats Effect 3 on Scala.js due to the change of the thread model.

Some JS functions such as Event.preventDefault() have to be run synchronously or won’t have any effect. In CE2, we can just use IO because it is run synchronously until a first async boundary. For example, if we wanted to implement some click event handler:

val more: IO[Unit] = ???
// OK in CE2, bad in CE3
def onClick(e: org.scalajs.dom.Event): IO[Unit] =
  IO{ e.preventDefault() } *> more

In CE3, we must use SyncIO without converting it into an IO. Unless I’m missing something, we have to resort to IO#unsafeRunAndForget:

val more: IO[Unit] = ???
// bad
def onClick(e: org.scalajs.dom.Event): SyncIO[Unit] =
  SyncIO{ e.preventDefault() }.to[IO] *> more
// OK
def onClick(e: org.scalajs.dom.Event): SyncIO[Unit] =
  SyncIO{ e.preventDefault(); more.unsafeRunAndForget() }
// OK
def onClick(e: org.scalajs.dom.Event): SyncIO[Unit] =
  SyncIO{ e.preventDefault() } *> SyncIO{ more.unsafeRunAndForget() }

The story is complicated because often more in the above example must be asynchronous. For example, it can be an AJAX call triggered by clicking a link. I guess this is going to be a common pattern in my project, and I definitely wouldn’t like to sprinkle unsafeRunAndForget all over it.

If there were IO#runAsync like in CE2, the last code could be rewritten like this:

def onClick(e: org.scalajs.dom.Event): SyncIO[Unit] =
  SyncIO{ e.preventDefault() } *> more.runAsync(_ => IO.unit)

(I’d like to point out IO#runAsync would be equivalent to runAff_ in purescript-aff, and IO#runAndForget would correspond to launchAff_.)

The migration guide refers to Dispatcher as the replacement of IO#runAsync but it doesn’t have any methods that return SyncIO[_]. I think it is reasonable because Dispatcher shouldn’t be coupled to SyncIO, but it may be helpful to have IO, as a concrete effect type, have a conversion from IO to SyncIO.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:39 (28 by maintainers)

github_iconTop GitHub Comments

2reactions
vasilmkdcommented, Nov 30, 2021

I’m not against a convenience method for this. I much prefer it over changing the execution model of IO.

1reaction
diesalblacommented, Nov 30, 2021

Doesn’t Stream.eval introduce an async barrier by raceing a cancelation effect against the main one? That might be old. Pinging @diesalbla for thoughts.

So, here is the code that “compiles” (in fs2 jargon) a Stream.eval, which is represented as an object of the Eval subclass of Pull, into the target effect type F: https://github.com/typelevel/fs2/blob/main/core/shared/src/main/scala/fs2/Pull.scala#L1027-L1036. It makes a call to the Scope.interruptibleEval method, which then refers to the InterruptibleContext.eval function. It is in the code of that last eval that the race you are referring to occurs.

    * When the stream is evaluated, there may be `Eval` that needs to be cancelled early,
    * when scope allows interruption.
    * Instead of just allowing eval to complete, this will race between eval and interruption promise.
    * Then, if eval completes without interrupting, this will return on `Right`.
Read more comments on GitHub >

github_iconTop Results From Across the Web

Static Collection update inside CompletableFuture#runAsync
Problem description: As I understand from concurrency point of view, static variable could NOT be shared between threads, so data can be lost ......
Read more >
the lag when scrolling, sending, and opening gifts on ...
If you slowly scroll though your friends list, let your phone cache the avatar images of each friend, then go back and view...
Read more >
Creating asyncAll(), asyncSettled(), And asyncRace() ...
Ben Nadel builds on top of Lucee's parallel iteration behavior and the runAsync() function to create the Promise-inspired functions: ...
Read more >
About Async tasks, the Get-Task cmdlet and a hash table
The New-VM cmdlet is executed with the -RunAsync parameter which means the script continues once the “Clone virtual machine” task is started.
Read more >
Improving Performance with Java's CompletableFuture
The Future interface provides only the get() method to retrieve the result of ... If we step back for a moment, we realize...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found