-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Promises extras update #758
Conversation
I'll look this over today or tomorrow. |
It's worth including a section in the docs or a blog post explaining the changes. In particular, the removal of subclassing support and the deprecation of |
|
**/ | ||
Promise.any = function (values) { | ||
return new Promise(function (resolve, reject) { | ||
if (values.length < 1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this fork be moved out of the Promise
constructor and return a static pre-resolved promise?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- verify
values
was passed to avoid the TypeError.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I intentionally avoided a check there because I want it to throw an early error, but I didn't want to add extra code like !isArray(values) && throw new TypeError(...)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A truthy check is all I had in mind. I wouldn't want to bog down the methods with isArray
, either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Getting back to this, I prefer it to throw. A wrong parameter here is a programmer error and as such it should fail fast. In fact, I think I should add
if (!Y.Lang.isArray(values)) { Y.log('TypeError: wrong parameter type', 'error'); }
...because if you pass a non null|undefined|arraylike value the result will be a forever pending promise, a hard thing to debug.
I'm starting to think I should split this kind of work into more specific pull requests rather than one big PR. |
Smaller PRs will get reviewed more thoroughly and promptly, for sure. But this one is ok as is. |
I made the following changes that you should review:
I also added most of the tests we discussed. I worked around the race condition in Promise.every() by resolving one of the promise synchronously and the rest asynchronously. I still need to add the tests for the combinator functions without params. I'm hoping we can reach an agreement on that. Coverage is back to 100%.
|
Oh! I just found this comment. I'll take a look at this on Monday. |
No worries. We were under code freeze, so I also put it on hold. I still need to work on the docs changes. I also want to add to the docs a short section about the reasoning behind having separate promise and resolver objects. I've been asked a lot of questions about that. |
// This essentially makes the process recursive, flattening | ||
// promises for promises. This is still a topic of discussion | ||
// in the community | ||
self.resolve(x); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As of the date of this comment, promises aren't flattened, only thenables. Promise.isPromise(x)
returns false positives for unknown thenables, so this treats promises and thenables identically, which doesn't satisfy 1.1.
I'm open to suggestions on how to reconcile the issue. IMO, Promise.isPromise(x)
should return true
for instances of Y.Promise from another YUI instance or another window.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I was following DOM Promise here. I think we need to discuss branding again. If the whole point of A+ is to provide interoperability it'd a shame not to be able to identify other valid promises implementations.
BTW I've been meaning to review this section again. I think I'm creating too many anonymous functions so it may be a good idea to define resolve
and reject
in the instance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, that's not a good idea: http://jsperf.com/fn-wrap-vs-nowrap
The resolver does not need to know about the promise anymore. It was used before to return an instance of promise.constructor
The standard is still a moving target on this
Adding |
Brings coverage back up to 100%
As per the DOM spec
@lsmith I misread the spec and it is using multiple arguments instead of an array, so that nulls are argument about empty lists for combinator methods. I mentioned it to Domenic and Alex Russell but it seems that it'll stay that way. See slightlyoff/Promises#70 I'll document the other combinators and send this off so I can get to work on synchronous resolution and other performance improvements. |
Oh boy, that sucks. varargs is a terrible idea. I saw the same thing right away when using Y.batch(). |
I know. I want to leave the door open for conditional loading in the |
That follows Can you bring that up in yui-contrib or the weekly round table? |
If the intent is to mirror |
@rgrove the issue we're discussing is that |
I really want to make this a polyfill for ES/DOM promises. We'll probably see them in Firefox in the next months. That's why I don't want to introduce new methods that won't be in the ES/DOM spec. And while most of the features this PR introduces will be in the spec, the names of all methods and details of their implementation are still shifting. So I'll close this PR and send more atomic PRs. The first one will probably just be a cleanup to reduce the number of objects created in each iteration and to add a first implementation of If anyone wants more details just let me know and I'll post to yui-contrib. |
This pull request splits the
promise
module into two modules:promise-core
andpromise-extras
. Thepromise
name is still an alias that loads these two new modules. The core module has little changes and the extras module introduces new features.Changes from previous version
resolver.resolve
resolver.resolve
promise.getStatus
is now only available when including thepromise-extras
modulepromise.then
no longer returns an instance ofpromise.constructor
. Instead it always return a bare Promise with no subclassingY.batch
is deprecated in favor ofY.Promise.every
. Resolves [Promise] Y.batch should accept and flatten nested arrays #740New features
promise.done()
.done
behaves in a simlar way tothen
, but it doesn't return a new promise and it doesn't catch errors to turn them into rejections. `fail is aPromise.resolve
andPromise.reject
for easier creation of already resolved promisesPromise.every
,Promise.any
andPromise.some
. Resolves Y.batch() and other Promise related methods should be static on Y.Promise #670Promise.accept
from the DOM standard because it opens the door for promises for promises which I don't think we want unless proven useful. It can be added later.Changes in the docs
batch
from the docs.Promise(function (fulfill) ...
to using "resolve"Promises/A+
Test results
I'll work on getting that 100% on branches back.
I created a new branch with no commit history because I went back and forth a bit with some changes and I reached nearly 30 commits.