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

Need a way to synchronously resolve a Future #47

Open
sicking opened this issue Mar 14, 2013 · 9 comments
Open

Need a way to synchronously resolve a Future #47

sicking opened this issue Mar 14, 2013 · 9 comments

Comments

@sicking
Copy link
Contributor

sicking commented Mar 14, 2013

For background and details, see
http://lists.w3.org/Archives/Public/www-dom/2013JanMar/0202.html
http://lists.w3.org/Archives/Public/www-dom/2013JanMar/0205.html

In short, in some cases we need the ability to resolve a Future synchronously. In particular, for some APIs it's important that the callback which indicates success/failure happens at a particular instance.

For Event dispatch, it's important that the callback is called during the actual event dispatch. Otherwise doing things like calling Event.preventDefault() or Event.stopPropagation() will have no effect.

There will likely be other similar scenarios. I could definitely imagine that we'll run into situations when we'd want to do something like:

function topLevelCallback() {
  setState1();
  resolver1.accept(...);
  setState2();
  resolver2.accept(...);
  setState3();
}

where topLevelCallback is called as a separate microtask and where we want the callbacks which are triggered by resolver 1 to see "state 1" and the callbacks triggered by resolver 2 to see "state 2".

Ideally the cases when we need to synchronously resolve a Future will be rare and will only happen when we're basically at the top of the callstack. Synchronously dispatching Events is an obvious exception and really is a wart, but one that we're many years too late to fix.

@domenic
Copy link
Collaborator

domenic commented Mar 14, 2013

I think this is a very strong indication that you are trying to use DOMFutures somewhere where they don't belong. Promises represent asynchronous operations; to represent a synchronous operation, you should use a function call.

@sicking
Copy link
Contributor Author

sicking commented Mar 14, 2013

So you think we should not have a EventTarget.once function then? I certainly believe that that's a valid answer, it just would have been cool if we could make that work. Note that most events are asynchronous, just not all of them.

Firing the .then-callback at a very specific time certainly goes against the idea that you can register .then-callbacks much after a promise has been resolved. So I can definitely see that as an argument that this issue should be rejected. But it does limit the types of asynchronous patterns that we can solve with Futures.

@domenic
Copy link
Collaborator

domenic commented Mar 14, 2013

I think EventTarget.once should exist but not return a DOMFuture (i.e. it should act the same as Backbone or Node's once or jQuery's one).

Firing the .then-callback at a very specific time certainly goes against the idea that you can register .then-callbacks much after a promise has been resolved.

I didn't even realize this aspect of your proposal. The idea would be that attaching a handler with then after the event has fired does nothing? E.g.

let future = myElement.once("focus");

future.then(() => console.log("1"));

myElement.focus(); // synchronously logs "1", eek.

future.then(() => console.log("2")); // but "2" is never logged!?!?

If so, this breaks some of the most fundamental rules of promises, and further indicates they're the wrong abstraction here.

@domenic
Copy link
Collaborator

domenic commented Mar 14, 2013

On further thought, this seems somewhat similar to #37, where you're trying to use promises to model streams. Events are definitely streams, not promises. (See functional reactive programing.)

The only confounding factor is that there are some events that really should be promises, like DOMContentLoaded. (After all, if DOMContentLoaded has already fired, you still want your handler to go, as shown by jQuery's "ready" behavior.)

@sicking
Copy link
Contributor Author

sicking commented Mar 15, 2013

No, the console.log("2") would still happen. It would just happen when the world is in a different state. All I'm saying is that my proposal tries to guarantee that an early-registered callback would see a specific state of the world. Late-registered callbacks would see a different state.

I also don't understand what you are saying about proposal #37. It only uses Futures to model a single value from the stream, as well as a (separate) Future for modeling the end of a stream. But it seems like this discussion belongs over in #37.

@sicking
Copy link
Contributor Author

sicking commented Mar 17, 2013

I think the higher meta-question here is: Are Futures appropriate to use in situations when we want to asynchronously deliver a success/error signal, but where it's critical that the signal is delivered while the surrounding world is in a particular state.

As things stand right now, Events are a good fit in situations when you have callbacks that fire zero to multiple times, particularly in response to UI actions.

Futures are a good fit in situations when you have a result which is delivered asynchronously, and that result is either a value or an error.

The question in this issue is: Are Futures a good fit when you have a result which is delivered asynchronously, and it's important that the world is in a particular state when the value is delivered.

I think it's ok to say "no". Trying to ensure that the world is in a particular state, especially through chained Futures, is non-trivial. But it does potentially lose us a lot of use cases were we can't use Futures, and will have to use plain callbacks or Events.

@slightlyoff
Copy link
Owner

I'm trying to understand what guarantees about the world's state are required, and why they aren't being packed into the value passed to the future instead of being left in the environment?

@sicking
Copy link
Contributor Author

sicking commented Apr 15, 2013

@juandopazo
Copy link

DOMFuture used to have a way to resolve synchronously. It made a lot of sense for cases in which we know that at resolution time we're in another tick, like in after a network request, to avoid an unnecessary performance hit. Does anyone know why it was removed?

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