-
-
Notifications
You must be signed in to change notification settings - Fork 149
Introduce ExtendedPromiseInterface #19
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
Conversation
This interface can be used for useful shortcut and utility methods which are not part of the Promises/A specification.
Just read the code: if I throw a |
Sure, you can abuse that and get unpredictable results ;) |
done() now only wraps the UnhandledRejectionException if the rejection value isn't an exception. Also, more tests.
@nicolas-grekas See c0ba5c3. UnhandledRejectionException is now only a wrapper for non-exception rejection values. |
Thanks I should test now! Reading the code, I think some type hints/instanceof should be changed from |
👍 from me: it solves my debugging experience problem, thanks! |
Avoids confusion with ExtendedPromiseInterface::progress. A Deferred::progress alias is still available for backward compatibility.
…o catch specific errors.
All proposed methods are now implemented. |
You mentioned in the description that there may be a performance concern with _checkTypeHint. You could measure the performance impact by comparing it against a baseline of just providing a class name followed by a callback function. For example: $promise
->otherwise('RuntimeException', function(\RuntimeException $reason) {
// Only catch \RuntimeException instances
})
->otherwise('Exception', function(\Exception $reason) {
// Only catch \Exception instances
})
->otherwise(function($reason) {
// Catch other errors
}); |
Yes, that's something to consider. I had this version locally but i didn't liked the unexplicit argument signature. Alternatively, there could be 2 methods, The typehint check is only done in |
I did a quick benchmark with your proposed otherwise() implemention. Implementation: https://gist.github.com/jsor/885c4b54b325ac3d5c7f#file-otherwise-php Results for 1000 iterations
Performance impact seems to be neglible, but memory usage is much higher for the typehint variant. |
Are you going to add an |
No, the plan for 3.0 is to merge the ExtendedPromiseInterface (and CancellablePromiseInterface) into PromiseInterface. PromiseInterface would then just mark promises created by React/Promise with the full API. If you're dealing with untrusted promises, i recommend a little helper function similar to React\resolve: function resolveExtended($promiseOrValue = null)
{
if ($promiseOrValue instanceof ExtendedPromiseInterface) {
return $promiseOrValue;
}
if ($promiseOrValue instanceof PromiseInterface) {
return new Promise(function ($resolve, $reject, $notify) use ($promiseOrValue) {
$promiseOrValue->then($resolve, $reject, $notify);
});
}
return new FulfilledPromise($promiseOrValue);
} Do you have a use case where such an interface whould be helpful? |
Makes sense. Adding many more methods to PromiseInterface will change the way I glue my library and react promises together though. Instead of having my objects implement PromiseInterface (which would have 7 methods now I believe), I would implement PromisorInterface and provide a |
React/Promise could provide a Trait for otherwise()/always()/progress() since they all are just shortcuts around then(). The only methods which must be implemented are done() and cancel() (which you provide anyway). But i see your point. Will think this through and will definitely get your feedback before doing anything like this. |
Throwing this out there, though I'm not sure if it's a good idea... What about adding a |
👍 for a |
Funny, i was about to propose the same :) An alternative would be to handle it like in JavaScript land: All major promise libs allow arbitrary promises as input simply by checking if there's a |
If you do make a change to support something like this, then I would vote for an interface over duck typing because you save the overhead of having to call method_exists() every time you do anything related to promises. |
Conflicts: CHANGELOG.md README.md src/Deferred.php src/FulfilledPromise.php src/LazyPromise.php src/Promise.php src/RejectedPromise.php tests/PromiseTest/FullTestTrait.php tests/PromiseTest/PromiseFulfilledTestTrait.php tests/PromiseTest/PromisePendingTestTrait.php tests/PromiseTest/PromiseRejectedTestTrait.php tests/PromiseTest/PromiseSettledTestTrait.php
+1 for |
No major objections to the patch, though it does feel a bit bloaty. In particular, I feel like forcing every promise to implement Not sure if that's feasible though. And consistent with whatever javascript-kiddies are doing. |
After looking at the Promises/A+ spec a bit more in-depth, I see that they just say to use untrusted promises that have a then() method. I'm actually very much in favor of that. You could even check if a promise you're given is first Thennable, then check if it has a then method (that is, if foreign promises need to be treated differently for some reason). This would allow react to interop with any other promise libraries (which would be great because I just wrote one, but it has a different design and abstractions, but still implements the same spec). |
That was what i proposed here :) |
Totally! I was wrong! You should just check for a then method. I don't think there needs to be a PSR either (I think the A+ spec is enough). There might not even need to be a Thennable interface really. |
👍 |
Due to limitations in the PHP language these methods these two methods couldn't use keywords as names. With PHP 7+ this is possible, and it makes it a lot clearer what the methods do. Refs: #19
Due to limitations in the PHP language these methods these two methods couldn't use keywords as names. With PHP 7+ this is possible, and it makes it a lot clearer what the methods do. Refs: reactphp#19
Due to limitations in the PHP language these methods these two methods couldn't use keywords as names. With PHP 7+ this is possible, and it makes it a lot clearer what the methods do. Refs: reactphp#19
Due to limitations in the PHP language these two methods couldn't use keywords as names. With PHP 7+ this is possible, and it makes it a lot clearer what the methods do. Refs: reactphp#19
Due to limitations in the PHP language these two methods couldn't use keywords as names. With PHP 7+ this is possible, and it makes it a lot clearer what the methods do. Refs: reactphp#19
The ExtendedPromiseInterface extends the PromiseInterface with useful shortcut
and utility methods which are not part of the Promises/A specification.
Implemented methods:
ExtendedPromiseInterface::done()
Status: Implemented
When working with promises, it's a common issue that exceptions (and/or rejections) get lost because there is no way to break out of a promise chain.
With the new
ExtendedPromiseInterface::done()
you can end a promise chain and unhandled rejections/exceptions will be rethrown in an uncatchable way causing a fatal error.See:
ExtendedPromiseInterface::otherwise()
Status: Implemented
Shorthand for
$promise->then(null, $onRejected)
.Additionally, you can type hint the
$reason
argument of$onRejected
to catch only specific errors.Example:
The typehint is checked via reflection from
$onRejected
. Performance impact?See:
ExtendedPromiseInterface::always()
Status: Implemented
The
$onFulfilledOrRejected
handler gets called, with no arguments, when the promise either fulfills or rejects.Example
See:
ExtendedPromiseInterface::progress()
Status: Implemented
Shorthand for
$promise->then(null, null, $onProgress)
.See:
I would love to hear feeback