Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conditions signaled from promises are invisible to the invoking environment #70

Closed
tzakharko opened this issue Jul 2, 2021 · 7 comments

Comments

@tzakharko
Copy link

It seems that any signaled condition inside a promise is gobbled up by some hidden mechanism and will not be visible to the external handlers. The attached code illustrates this with messages (because they have a clear side effect), but I also tried it with other signals with the same effect.

Is there any obvious way to access signaled conditions outside of using external mechanisms (e.g. a callback).

library(promises)

withCallingHandlers({
    promise(~ {
     later::later(~ {
        message("this is a message")
        resolve(TRUE)
     })
    }) %>% finally(~ {
      message("we are done")
      cat("Promise is resovled\n")
    })
  
  
    while(!later::loop_empty()) {
      later::run_now()
      Sys.sleep(0.1)
      message("from the main loop")
    }
  },
  message = function(cnd) {
    cat("Got message:", cnd$message)
  }
)
#> Got message: from the main loop
#> from the main loop
#> Promise is resovled
#> Got message: from the main loop
#> from the main loop
#> Got message: from the main loop
#> from the main loop
@tzakharko
Copy link
Author

After digging a bit into this I realized that this is a limitation of later, so I will ask this question there.

@bartekch
Copy link

@tzakharko what issue in later is this? Is it solved maybe?

@gadenbuie
Copy link
Member

I didn't find any issues in later opened by @tzakharko or that match the topic discussed here.

It's hard to tell the full context of the original question, but if you're wanting to handle errors from code being evaluated as a promise, I recommend taking a look at the Access the results of a promise article in the promises docs. You can use the onRejected argument of then() or the catch() function to handle errors that are signaled in a promise chain.

@bartekch do feel free to open a new issue for your question, especially if you can create a reprex for it.

@tzakharko
Copy link
Author

I have to admit that I don't remember the exact context. It doesn't seem I ever opened an issue with later, so I suppose I have abandoned this particular line of inquiry. At any rate, I have tried this snippet and it still does not handle the conditions from inside the promise.

@gadenbuie
Copy link
Member

@tzakharko Thanks for checking back in! In terms of the snippet in this issue; it's definitely not expected to work. The conditions aren't signaled in a place visible to withCallingHandlers() in the parent process. To handle errors, you need to use catch() or the onRejected argument of then(). You might be able to catch other conditions in this way, too, or you might need to bring the condition handler into the block being evaluated in a promise.

@jcheng5
Copy link
Member

jcheng5 commented Jun 14, 2023

For (very) advanced scenarios, you can accomplish something that's sort of like withCallingHandlers for promises with promise domains: https://rstudio.github.io/promises/reference/with_promise_domain.html

Though, I would be slightly surprised if this is useful to anyone, unless they are writing a framework of some kind.

@bartekch
Copy link

bartekch commented Jun 15, 2023

@gadenbuie my case is almost exactly the same as OP - I want to intercept messages signaled in onFulfilled (or onRejected, same story). Simplest example.

withCallingHandlers(
  {
    message("This message will be caught")
    promises::future_promise(Sys.sleep(1)) |>
      promises::then(function() message("I want this meesage to be caught as well"))
  },
  message = function(cnd) {
    message("Got message: ", cnd$message)
  }
)
#> Got message: This message will be caught

#> This message will be caught
#> I want this meesage to be caught as well

I thought that it would work, since callback is run in the original process. I also got confused by the sentence However, it’s perfectly fine to read reactive values/expressions from inside a promise handler. Handlers run in the original process, not a child process, so reactive operations are allowed. in vignette about promises in Shiny (my actual case is intercepting all messages in Shiny app and appending common prefix, for logging purposes, but I guess it doesn't really matter).

From your comments I infer that it does NOT work like that. And, after some consideration, it actually makes some sense, because whole call to withCallingHandlers is completed before promise is resolved. It's just a little less obvious when running sequentially (or inside Shiny, as I did). Hence I won't open another issue for this.

@jcheng5 I'm not exactly sure how should I use domains to address my issue, but anyway it seems like way too complicated for what I need, thanks for suggestion though!

In the meantime I believe I found the forementioned issue in later - still open though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants