-
Notifications
You must be signed in to change notification settings - Fork 165
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
A way of synchronously retrieving fulfillment values and rejection reasons #61
Comments
My initial idea (not great though, I admit):
The last bullet point could be replaced by three booleans ( Alternately the predicates could be on some "promise tester object", which in practice always ends up being the promise library's main entry point, e.g. |
I'm not a fan of synchronous value/state extraction, in general, but if there are compelling practical use cases, I can probably be swayed. I just worry about people doing strange things like polling a promise using That said, I prefer If I understand |
Agreed. It's the templating use case that really convinced me.
+1
I'm pretty sure this is correct. |
A link to this would be great for my education since every use case for sync value/state extraction I've seen so far has been due to sync/async interaction which could be handled in a better manner. Thanks! |
@wycats want to help @unscriptable out with an example? |
I think logically |
I too am not so much of a fan of my Q’s naming conventions in this matter either, but the algorithm is solid. I might be convinced to change the names. I might also be convinced to change
function isPending(object) {
return !isFulfilled(object) && !isRejected(object);
}
function isFulfilled(object) {
return !isPromise(object) || "value" in object.mostResolved();
}
function isRejected(object) {
return isPromise(object) && "error" in object.mostResolved();
} |
@kriskowal This looks pretty good to me at first glance. Maybe s/error/reason, but that's very minor. I need to digest it a bit more, tho ... hopefully over the weekend. |
@kriskowal wow, that really clarifies the meaning of I'm also quite happy about the use of |
@domenic Replace |
Very, very interesting. I actually like that devs have to do something more involved than .then() to "get at the value synchronously". Hopefully, it makes them think twice. :) I agree @domenic: returning a promise also helps make it more apparent what's really going on (imho, anyway). This may be a bit off-topic, but can somebody succinctly describe why "nearer" is a good alternative to "mostResolved" (ignoring the r-word argument). |
@unscriptable Only Mark Miller could succinctly explain that. Using promises as proxies for remote objects introduces more kinds of promises, like Near promises and Far promises. A far promise can be fulfilled remotely, resolved locally, but still represented as a promise object. |
I did a quick experiment to get my head around this approach in cujojs/when@f929a35. And here is a gist with a simple node test program, and its output. It turned out to be quite simple to implement. One interesting issue it raised was what to do with a promise-like thenable that doesn't support For fun, I tried out the name Anyway, I'm still not sold on the need for this, so it'll be great to hear from @wycats on some concrete use cases. |
I found it worthwhile when building QEJS (an asynchronous templating library). The issue there was that I had vast arrays of mostly strings, with a few promises for strings, and a few promises for arrays of strings and so on in a big nested structure. Most of the promises in the array would end up being resolve long before I actually asked for their value. Before optimizing the handling of pre-resolved promises it was unbearably slow, but after it was OK. Sadly I didn't do any proper benchmarks, I just left it with the fact that it made the application noticeably snappier. I was using |
Hmmm, just had the thought that what |
I quite like I think naming of it isn't too important though, other than avoiding something really stupid and avoiding conflicting with anything that's used elsewhere. This method (whatever we call it) will only really be intended for internal use by other promise libraries, so we're talking about advanced users (unlike with |
I don’t think there is a way around using the terms |
An alternative would be something along the lines of: promise
.asap(function (value) {
}, function (err) {
}); Which would discourage people from relying on this method eventually becoming synchronous. It would essentially be equivalent to |
I've created a new repo for this: https://github.com/promises-aplus/synchronous-inspection-spec Mainly because we need something like this to fix Q's current implementation. |
@domenic Can you elaborate a bit on that last comment? What needs fixing? I thought that Q implements something along the lines of the |
@briancavalier Q has a bug wherein synchronously inspecting a promise rejected with a falsy value does not show it to be rejected, so we just need to fix that. Thus some of the schemes shown here make sense as a fix, since they correctly distinguish.
|
@domenic, |
@kriskowal why is it necessary? It's necessary in Q currently, but why is it inherently necessary? Such a promise still has a fulfillment value and rejection reason which it would be fine to expose separately from |
This is a new idea that does not belong in the base spec; we are just using this issue tracker as a place for discussion.
Over in kriskowal/q#167, we're contemplating how to retrieve the value of a foreign fulfilled or rejected promise. The use case there is having an
isPending(possiblyForeignPromise)
predicate that doesn't give false positives, but I think the most compelling use case is speed for e.g. templating systems (to avoid DOM manipulation). I believe @ForbesLindesay has mentioned this being used in q-ejs, and I know @wycats had some interest in the issue as well. I've also heard second-hand that @lukehoban wasn't sure promises could be always-asynchronous because of such use cases.This is largely a bikeshedding matter, but it'd be nice to have an interoperable standard. Currently Q uses the following semantics, which to be honest I'm not a huge fan of:
promise.valueOf()
on a pending or rejected promise: returnspromise
.promise.valueOf()
on a fulfilled promise: returns the fulfillment value.promise.valueOf().exception
on a rejected promise: returns the rejection reason.Other prior art:
resolvedValue
andrejectedValue
. Problems: uses the horribly-confusing term "resolve," and no way to distinguish between pending vs. fulfilled or rejected withundefined
.promise.nearer()
is like Q'spromise.valueOf()
The text was updated successfully, but these errors were encountered: