Skip to content

Deferred: Deprecate deferred.pipe(), isResolved(), isRejected() #101

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ module.exports = function(grunt) {
"src/manipulation.js",
"src/event.js",
"src/traversing.js",
"src/deferred.js",
"src/outro.js"
],
tests: {
Expand Down
63 changes: 63 additions & 0 deletions src/deferred.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@

var oldDeferred = jQuery.Deferred,
tuples = [
// action, add listener, callbacks, .then handlers, final state
[ "resolve", "done", jQuery.Callbacks("once memory"),
jQuery.Callbacks("once memory"), "resolved" ],
[ "reject", "fail", jQuery.Callbacks("once memory"),
jQuery.Callbacks("once memory"), "rejected" ],
[ "notify", "progress", jQuery.Callbacks("memory"),
jQuery.Callbacks("memory") ]
];

jQuery.Deferred = function( func ) {
var deferred = oldDeferred(),
promise = deferred.promise();

deferred.pipe = promise.pipe = function( /* fnDone, fnFail, fnProgress */ ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's an extra space after the second "=", and the indentation looks wrong from here down.

var fns = arguments;

migrateWarn( "deferred.pipe() is deprecated" );

return jQuery.Deferred(function( newDefer ) {
jQuery.each( tuples, function( i, tuple ) {
var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
// deferred.done(function() { bind to newDefer or newDefer.resolve })
// deferred.fail(function() { bind to newDefer or newDefer.reject })
// deferred.progress(function() { bind to newDefer or newDefer.notify })
deferred[ tuple[1] ](function() {
var returned = fn && fn.apply( this, arguments );
if ( returned && jQuery.isFunction( returned.promise ) ) {
returned.promise()
.done( newDefer.resolve )
.fail( newDefer.reject )
.progress( newDefer.notify );
} else {
newDefer[ tuple[ 0 ] + "With" ](
this === promise ? newDefer.promise() : this,
fn ? [ returned ] : arguments
);
}
});
});
fns = null;
}).promise();

};

deferred.isResolved = function() {
migrateWarn( "deferred.isResolved is deprecated" );
return deferred.state() === "resolved";
};

deferred.isRejected = function() {
migrateWarn( "deferred.isRejected is deprecated" );
return deferred.state() === "rejected";
};

if ( func ) {
func.call( deferred, deferred );
}

return deferred;
};
181 changes: 181 additions & 0 deletions test/deferred.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@

module("deferred");

test( ".pipe() warnings", function( assert ) {
assert.expect( 4 );

var d = jQuery.Deferred(),
p = d.promise();

function checkValue( v ) {
assert.equal( v, 1, "got correct value" );
}

// Deferred
expectWarning( "pipe", function() {
d.pipe( checkValue );
});

// Deferred's promise object
expectWarning( "pipe", function() {
p.pipe( checkValue );
});

// Should happen synchronously for .pipe()
d.resolve( 1 );
});

test( "[PIPE ONLY] jQuery.Deferred.pipe - filtering (fail)", function( assert ) {

assert.expect( 4 );

var value1, value2, value3,
defer = jQuery.Deferred(),
piped = defer.pipe( null, function( a, b ) {
return a * b;
}),
done = jQuery.map( new Array( 3 ), function() { return assert.async(); } );

piped.fail(function( result ) {
value3 = result;
});

defer.fail(function( a, b ) {
value1 = a;
value2 = b;
});

defer.reject( 2, 3 ).pipe( null, function() {
assert.strictEqual( value1, 2, "first reject value ok" );
assert.strictEqual( value2, 3, "second reject value ok" );
assert.strictEqual( value3, 6, "result of filter ok" );
done.pop().call();
});

jQuery.Deferred().resolve().pipe( null, function() {
assert.ok( false, "then should not be called on resolve" );
}).then( done.pop() );

jQuery.Deferred().reject().pipe( null, jQuery.noop ).fail(function( value ) {
assert.strictEqual( value, undefined, "then fail callback can return undefined/null" );
done.pop().call();
});
});

test( "[PIPE ONLY] jQuery.Deferred.pipe - deferred (progress)", function( assert ) {

assert.expect( 3 );

var value1, value2, value3,
defer = jQuery.Deferred(),
piped = defer.pipe( null, null, function( a, b ) {
return jQuery.Deferred(function( defer ) {
defer.resolve( a * b );
});
}),
done = assert.async();

piped.done(function( result ) {
value3 = result;
});

defer.progress(function( a, b ) {
value1 = a;
value2 = b;
});

defer.notify( 2, 3 );

piped.done(function() {
assert.strictEqual( value1, 2, "first progress value ok" );
assert.strictEqual( value2, 3, "second progress value ok" );
assert.strictEqual( value3, 6, "result of filter ok" );
done();
});
});

test( "[PIPE ONLY] jQuery.Deferred.pipe - context", function( assert ) {

assert.expect( 7 );

var defer, piped, defer2, piped2,
context = {},
done = jQuery.map( new Array( 4 ), function() { return assert.async(); } );

jQuery.Deferred().resolveWith( context, [ 2 ] ).pipe(function( value ) {
return value * 3;
}).done(function( value ) {
assert.strictEqual( this, context, "[PIPE ONLY] custom context correctly propagated" );
assert.strictEqual( value, 6, "proper value received" );
done.pop().call();
});

jQuery.Deferred().resolve().pipe(function() {
return jQuery.Deferred().resolveWith(context);
}).done(function() {
assert.strictEqual( this, context,
"custom context of returned deferred correctly propagated" );
done.pop().call();
});

defer = jQuery.Deferred();
piped = defer.pipe(function( value ) {
return value * 3;
});

defer.resolve( 2 );

piped.done(function( value ) {
assert.strictEqual( this, piped,
"default context gets updated to latest promise in the chain" );
assert.strictEqual( value, 6, "proper value received" );
done.pop().call();
});

defer2 = jQuery.Deferred();
piped2 = defer2.pipe();

defer2.resolve( 2 );

piped2.done(function( value ) {
assert.strictEqual( this, piped2,
"default context updated to latest promise in the chain (without passing function)" );
assert.strictEqual( value, 2, "proper value received (without passing function)" );
done.pop().call();
});
});

test( "isResolved() and isRejected()", function( assert ) {

assert.expect( 12 );

var defer = jQuery.Deferred();

expectWarning( "isResolved unresolved", function() {
assert.strictEqual( defer.isResolved(), false, "isResolved pending" );
});

expectWarning( "isRejected unresolved", function() {
assert.strictEqual( defer.isRejected(), false, "isRejected pending" );
});

defer.resolve( 1 );

expectWarning( "isResolved resolved", function() {
assert.strictEqual( defer.isResolved(), true, "isResolved resolved" );
});

expectWarning( "isResolved resolved", function() {
assert.strictEqual( defer.isRejected(), false, "isRejected resolved" );
});

defer = jQuery.Deferred().reject( 1 );

expectWarning( "isResolved resolved", function() {
assert.strictEqual( defer.isResolved(), false, "isResolved rejected" );
});

expectWarning( "isResolved resolved", function() {
assert.strictEqual( defer.isRejected(), true, "isRejected rejected" );
});
});
1 change: 1 addition & 0 deletions test/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
<script src="ajax.js"></script>
<script src="event.js"></script>
<script src="traversing.js"></script>
<script src="deferred.js"></script>
</head>
<body>
<div id="qunit"></div>
Expand Down
13 changes: 13 additions & 0 deletions warnings.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,19 @@ $(document).ajaxStart(function(){ $("#status").text("Ajax started"); });

**Solution**: Boolean properties should generally not be passed to `$().attr` at all; replace with `$().prop` unless you truly intend to update the underlying HTML *attribute*.

### JQMIGRATE: deferred.pipe() is deprecated

**Cause**: The `.pipe()` method on a `jQuery.Deferred` object was deprecated as of jQuery 1.8, when the `.then()` method was changed to perform the same function.

**Solution**: Change all occurrences of `.pipe()` to `.then()`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd add some text like "and ensure that you aren't relying on context/state propagation or synchronous callback invocation (which were dropped from .then() for Promises/A+ interoperability as of jQuery 3.0)".


### JQMIGRATE: deferred.isResolved() is deprecated
### JQMIGRATE: deferred.isRejected() is deprecated

**Cause**: As of jQuery 1.7, the `isResolved()` and `isRejected` methods of the `jQuery.Deferred` object have been deprecated. They were removed in jQuery 1.8 and are no longer available in later versions.

**Solution**: To determine the state of a Deferred object, call `deferred.state()` and check for the `"resolved"` or `"rejected"` string values.

### JQMIGRATE: jQuery.clean() is deprecated

**Cause**: `jQuery.buildFragment()` and `jQuery.clean()` are undocumented internal methods. The signature of `jQuery.buildFragment()` was changed in jQuery 1.8 and 1.9, and `jQuery.clean()` was removed in 1.9. However, we are aware of some plugins or other code that may be using them.
Expand Down