-
Notifications
You must be signed in to change notification settings - Fork 21
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
Don't throw an error when resolve() is called twice #43
Comments
I definitely didn't get this form Promises/A+ and it also seems weird to be able to do this. In my mind a promise effectively should become immutable as soon as it has been resolved (or failed). Maybe I'm not understanding this correctly. If so, please let me know. I tried fulfilling a promise twice in firefox, and |
Of course the handler should only be called once. But subsequent calls should just be ignored. $promise = new Promise;
$writer->onMessage([$promise, 'resolve']);
$promise->then(...); Should resolve with the first message. Instead, it will throw an error on the second, so I have to do this boilerplate code everywhere: $promise = new Promise;
$writer->onMessage(function ($msg) use ($promise) {
if ($promise->state === Promise::PENDING) {
$promise->fulfill($msg);
}
}); |
This behavior is speced here: https://promisesaplus.com/#point-59
|
Hi Felix, That's interesting. However, that paragraph does not refer to being able to resolve a promise more than once using the executor function. What that refers to is the value that is returned from one of the two $promise->then(
function() {
return $thisvalue;
}, function() {
return $orThisOne;
}
); If in the previous example $subPromise = new Promise();
// $this is the main promise.
$result = $this->onResolved($value);
if ($result instanceof Promise) {
$result->then(function($value) {
$subPromise->resolve($value);
});
} This line in the spec:
Only refers to a situation where in the past example So it doesn't specifically say that a Promise can be resolved more than once, and subsequent ones ignored, it just says that if the result of a This is in direct conflict with the other points in the spec: https://promisesaplus.com/#point-29
And this is more or less proof that "point 59" is solely for interopability with promises that are not Promise/A+ compliant. So with that being out of the way, the question then is does this change make sense for sabre/event? I would say that the benefit of being alerted when you attempt to resolve a promise more than once is a good one, and it has prevented me from introducing bugs or creating problems that would otherwise be silently ignored. I think this is a good thing considering that Promises are already quite hard to grasp. It's one extra protection that prevents you from making mistakes, and I would say that that's a good thing. I don't know if you care about using the $promise = new Promise;
$writer->once('message', [$promise, 'resolve']);
$promise->then(...); |
Might have read the spec wrong there, but it clearly is what all JavaScript engines implemented. ECMAScript spec also does not state that an error should be thrown:
Assert here just means:
This also makes a lot of sense, because neither Promises/A+ nor ES6 define any way to inspect the promise state. Something like Imo the error is better suited for a log message, like you get with bluebird for example, which also warns you against not-handled rejected promises. You could register a PSR-compatible logger interface. interface ProtocolReader {
onMessage(callable $listener);
} and with the event name as a string that obviously doesn't work. I could introduce a |
I think I maintain that the little bit of boilerplate is a bit annoying, but I think the feature is useful enough. Here's a quick function can use to resolve a promise, but only if it hasn't already: function resolveOnce($promise, $value) {
if ($promise->state === Promise::PENDING) {
$promise->resolve($value);
}
} That should alleviate your biggest frustration. I also wanted to comment further on this:
This is true, but the ES6 promise doesn't have a Anyway, closing this. Hope the function alleviates most of the pain for you! |
That is also how Promises/A+ spec behaves. It is very useful to register the fulfill function as an event handler for example and get the promise resolved as soon as it is called, no matter if it will be called more times afterwards.
The text was updated successfully, but these errors were encountered: