Skip to main content

Bug Tracker

Side navigation

#8067 closed bug (wontfix)

Opened January 26, 2011 08:56PM UTC

Closed January 27, 2011 09:02PM UTC

Last modified February 01, 2011 11:21AM UTC

If $.when() receives an object that has a method named "promise", it assumes the object is observable

Reported by: rmurphey Owned by: rmurphey
Priority: low Milestone: 1.next
Component: core Version: 1.5rc1
Keywords: Cc:
Blocked by: Blocking:
Description
Attachments (0)
Change History (9)

Changed January 26, 2011 08:57PM UTC by rmurphey comment:1

_comment0: Instead of just testing that the value passed to $.when has a promise method, we should probably check that the promise method returns an object with then and fail methods?1296075554676301

If the object has a promise method, that doesn't mean that what it returns is a promise (having, at least, a then method).

Changed January 26, 2011 09:37PM UTC by jitter comment:2

component: unfiledcore

Changed January 26, 2011 10:21PM UTC by jitter comment:3

owner: → jaubourg
status: newassigned

Changed January 26, 2011 11:37PM UTC by jaubourg comment:4

_comment0: Testing for then on the returned object doesn't ensure it is a promise either. \ \ http://jsfiddle.net/9fuHZ/ \ \ Design by convention has its limits and no matter how complicated the test becomes, you always ways around it.1296085077575061

Testing for then on the returned object doesn't ensure it is a promise either.

http://jsfiddle.net/9fuHZ/

Design by convention has its limits and no matter how complicated the test becomes, you always have ways around it.

Changed January 27, 2011 12:09AM UTC by jitter comment:5

owner: jaubourgrmurphey
status: assignedpending

Changed January 27, 2011 12:43AM UTC by jaubourg comment:6

And I'm not gifted with jsfiddle: http://jsfiddle.net/9fuHZ/7/

Changed January 27, 2011 03:35PM UTC by rmurphey comment:7

status: pendingnew

Replying to [comment:4 jaubourg]:

Testing for then on the returned object doesn't ensure it is a promise either. http://jsfiddle.net/9fuHZ/ Design by convention has its limits and no matter how complicated the test becomes, you always have ways around it.

As Dave Methvin pointed out to me in the IRC channel, if we don't know what the promise method on the object passed to $.when does, then we probably don't want to run it to see what it returns :)

Changed January 27, 2011 09:02PM UTC by jitter comment:8

priority: undecidedlow
resolution: → wontfix
status: newclosed

If I read this right this issue is settled. There is no foolproof way to check if a promise() function really returns a promise or something which looks like it.

Feel free to yell at me and to request this ticket to get reopened.

#!html
<h1 style="color:#fafafa">But it's not going to happen. No matter what you say</h1>

Changed February 01, 2011 11:21AM UTC by jaubourg comment:9

_comment0: Replying to [comment:7 rmurphey]: \ > Replying to [comment:4 jaubourg]: \ > > Testing for then on the returned object doesn't ensure it is a promise either. \ > > \ > > http://jsfiddle.net/9fuHZ/ \ > > \ > > Design by convention has its limits and no matter how complicated the test becomes, you always have ways around it. \ > \ > As Dave Methvin pointed out to me in the IRC channel, if we don't know what the promise method on the object passed to $.when does, then we probably don't want to run it to see what it returns :) \ \ What about an object that is observable but doesn't implement the promise interface? Just like a jQuery collection could end up being if something like http://bugs.jquery.com/ticket/7934 was to be implemented (and it makes no sense for a jQuery collection to implement the promise interface since it would only clobber jQuery.fn and be unnecessarily confusing). \ \ Remember that Deferreds implement the promise interface as a convenience and I'm beginning to believe it was a mistake seeing as it turns out to be a bit confusing and hinders the fact that promise() returns an immutable object while deferreds are, obviously, mutable. \ \ At any rate, I don't see this as any different from testing for the presence of a nodeType attribute to determine if an object is a DOM node. Something jQuery does everywhere in the code and that works perfectly as long as the convention is known and no-one attempts to break it. \ \ An earlier version had a specific object attached onto the promise method to "mark" it. But, not only can you work around it, but it would also make using a third-party promise very difficult (ie not a jQuery.Deferred promise, just some other code from another library that implements Promise/A). \ \ As it is today, all it takes to make a third party promise observable is this: \ \ // Make third-party promise observable \ thirdPartyPromise.promise = function() { \ return this; \ } \ \ // Or if the implementation is prototype base \ // Add to the prototype so that all promises are now \ // observable by jQuery \ ThirdPartyPromise.prototype.promise = function() { \ return this; \ } \ \ Another advantage is that, if the third-party is not Promise/A compliant, it's pretty easy to return a Promise/A compliant object by doing some more work in the newly created promise method. \ \ This is incidently why jQuery uses a promise method as opposed to a promise property (like dojo and some others do). \ \ Another advantage is that there are far less risks of false positive by using a method rather than a property.1296559589003690

Replying to [comment:7 rmurphey]:

Replying to [comment:4 jaubourg]: > Testing for then on the returned object doesn't ensure it is a promise either. > > http://jsfiddle.net/9fuHZ/ > > Design by convention has its limits and no matter how complicated the test becomes, you always have ways around it. As Dave Methvin pointed out to me in the IRC channel, if we don't know what the promise method on the object passed to $.when does, then we probably don't want to run it to see what it returns :)

What about an object that is observable but doesn't implement the promise interface? Just like a jQuery collection could end up being if something like http://bugs.jquery.com/ticket/7934 was to be implemented (and it makes no sense for a jQuery collection to implement the promise interface since it would only clobber jQuery.fn and be unnecessarily confusing).

Remember that Deferreds implement the promise interface as a convenience and I'm beginning to believe it was a mistake seeing as it turns out to be a bit confusing and hinders the fact that promise() returns an immutable object while deferreds are, obviously, mutable.

At any rate, I don't see this as any different from testing for the presence of a nodeType attribute to determine if an object is a DOM node. Something jQuery does everywhere in the code and that works perfectly as long as the convention is known and no-one attempts to break it.

An earlier version had a specific object attached onto the promise method to "mark" it. But, not only can you work around it, but it would also make using a third-party promise very difficult (ie not a jQuery.Deferred promise, just some other code from another library that implements Promise/A).

As it is today, all it takes to make a third party promise observable is this:

    // Make third-party promise observable
    thirdPartyPromise.promise = function() {
        return this;
    }

    // Or if the implementation is prototype base
    // Add to the prototype so that all promises are now
    // observable by jQuery
    ThirdPartyPromise.prototype.promise = function() {
        return this;
    }

Another advantage is that, if the third-party is not Promise/A compliant, it's pretty easy to return a Promise/A compliant object by doing some more work in the newly created promise method.

This is incidently why jQuery uses a promise method as opposed to a promise property (like dojo and some others do).

Another advantage is that there are far less risks of false positive by using a method rather than a property.