Skip to content

Commit 876fd4e

Browse files
committed
Deferred: Deprecate deferred.pipe(), isResolved(), isRejected()
Ref #89 Fixes #97 Closes #101
1 parent 047ec83 commit 876fd4e

File tree

5 files changed

+259
-0
lines changed

5 files changed

+259
-0
lines changed

Gruntfile.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ module.exports = function(grunt) {
2828
"src/manipulation.js",
2929
"src/event.js",
3030
"src/traversing.js",
31+
"src/deferred.js",
3132
"src/outro.js"
3233
],
3334
tests: {

src/deferred.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
2+
var oldDeferred = jQuery.Deferred,
3+
tuples = [
4+
// action, add listener, callbacks, .then handlers, final state
5+
[ "resolve", "done", jQuery.Callbacks("once memory"),
6+
jQuery.Callbacks("once memory"), "resolved" ],
7+
[ "reject", "fail", jQuery.Callbacks("once memory"),
8+
jQuery.Callbacks("once memory"), "rejected" ],
9+
[ "notify", "progress", jQuery.Callbacks("memory"),
10+
jQuery.Callbacks("memory") ]
11+
];
12+
13+
jQuery.Deferred = function( func ) {
14+
var deferred = oldDeferred(),
15+
promise = deferred.promise();
16+
17+
deferred.pipe = promise.pipe = function( /* fnDone, fnFail, fnProgress */ ) {
18+
var fns = arguments;
19+
20+
migrateWarn( "deferred.pipe() is deprecated" );
21+
22+
return jQuery.Deferred(function( newDefer ) {
23+
jQuery.each( tuples, function( i, tuple ) {
24+
var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
25+
// deferred.done(function() { bind to newDefer or newDefer.resolve })
26+
// deferred.fail(function() { bind to newDefer or newDefer.reject })
27+
// deferred.progress(function() { bind to newDefer or newDefer.notify })
28+
deferred[ tuple[1] ](function() {
29+
var returned = fn && fn.apply( this, arguments );
30+
if ( returned && jQuery.isFunction( returned.promise ) ) {
31+
returned.promise()
32+
.done( newDefer.resolve )
33+
.fail( newDefer.reject )
34+
.progress( newDefer.notify );
35+
} else {
36+
newDefer[ tuple[ 0 ] + "With" ](
37+
this === promise ? newDefer.promise() : this,
38+
fn ? [ returned ] : arguments
39+
);
40+
}
41+
});
42+
});
43+
fns = null;
44+
}).promise();
45+
46+
};
47+
48+
deferred.isResolved = function() {
49+
migrateWarn( "deferred.isResolved is deprecated" );
50+
return deferred.state() === "resolved";
51+
};
52+
53+
deferred.isRejected = function() {
54+
migrateWarn( "deferred.isRejected is deprecated" );
55+
return deferred.state() === "rejected";
56+
};
57+
58+
if ( func ) {
59+
func.call( deferred, deferred );
60+
}
61+
62+
return deferred;
63+
};

test/deferred.js

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
2+
module("deferred");
3+
4+
test( ".pipe() warnings", function( assert ) {
5+
assert.expect( 4 );
6+
7+
var d = jQuery.Deferred(),
8+
p = d.promise();
9+
10+
function checkValue( v ) {
11+
assert.equal( v, 1, "got correct value" );
12+
}
13+
14+
// Deferred
15+
expectWarning( "pipe", function() {
16+
d.pipe( checkValue );
17+
});
18+
19+
// Deferred's promise object
20+
expectWarning( "pipe", function() {
21+
p.pipe( checkValue );
22+
});
23+
24+
// Should happen synchronously for .pipe()
25+
d.resolve( 1 );
26+
});
27+
28+
test( "[PIPE ONLY] jQuery.Deferred.pipe - filtering (fail)", function( assert ) {
29+
30+
assert.expect( 4 );
31+
32+
var value1, value2, value3,
33+
defer = jQuery.Deferred(),
34+
piped = defer.pipe( null, function( a, b ) {
35+
return a * b;
36+
}),
37+
done = jQuery.map( new Array( 3 ), function() { return assert.async(); } );
38+
39+
piped.fail(function( result ) {
40+
value3 = result;
41+
});
42+
43+
defer.fail(function( a, b ) {
44+
value1 = a;
45+
value2 = b;
46+
});
47+
48+
defer.reject( 2, 3 ).pipe( null, function() {
49+
assert.strictEqual( value1, 2, "first reject value ok" );
50+
assert.strictEqual( value2, 3, "second reject value ok" );
51+
assert.strictEqual( value3, 6, "result of filter ok" );
52+
done.pop().call();
53+
});
54+
55+
jQuery.Deferred().resolve().pipe( null, function() {
56+
assert.ok( false, "then should not be called on resolve" );
57+
}).then( done.pop() );
58+
59+
jQuery.Deferred().reject().pipe( null, jQuery.noop ).fail(function( value ) {
60+
assert.strictEqual( value, undefined, "then fail callback can return undefined/null" );
61+
done.pop().call();
62+
});
63+
});
64+
65+
test( "[PIPE ONLY] jQuery.Deferred.pipe - deferred (progress)", function( assert ) {
66+
67+
assert.expect( 3 );
68+
69+
var value1, value2, value3,
70+
defer = jQuery.Deferred(),
71+
piped = defer.pipe( null, null, function( a, b ) {
72+
return jQuery.Deferred(function( defer ) {
73+
defer.resolve( a * b );
74+
});
75+
}),
76+
done = assert.async();
77+
78+
piped.done(function( result ) {
79+
value3 = result;
80+
});
81+
82+
defer.progress(function( a, b ) {
83+
value1 = a;
84+
value2 = b;
85+
});
86+
87+
defer.notify( 2, 3 );
88+
89+
piped.done(function() {
90+
assert.strictEqual( value1, 2, "first progress value ok" );
91+
assert.strictEqual( value2, 3, "second progress value ok" );
92+
assert.strictEqual( value3, 6, "result of filter ok" );
93+
done();
94+
});
95+
});
96+
97+
test( "[PIPE ONLY] jQuery.Deferred.pipe - context", function( assert ) {
98+
99+
assert.expect( 7 );
100+
101+
var defer, piped, defer2, piped2,
102+
context = {},
103+
done = jQuery.map( new Array( 4 ), function() { return assert.async(); } );
104+
105+
jQuery.Deferred().resolveWith( context, [ 2 ] ).pipe(function( value ) {
106+
return value * 3;
107+
}).done(function( value ) {
108+
assert.strictEqual( this, context, "[PIPE ONLY] custom context correctly propagated" );
109+
assert.strictEqual( value, 6, "proper value received" );
110+
done.pop().call();
111+
});
112+
113+
jQuery.Deferred().resolve().pipe(function() {
114+
return jQuery.Deferred().resolveWith(context);
115+
}).done(function() {
116+
assert.strictEqual( this, context,
117+
"custom context of returned deferred correctly propagated" );
118+
done.pop().call();
119+
});
120+
121+
defer = jQuery.Deferred();
122+
piped = defer.pipe(function( value ) {
123+
return value * 3;
124+
});
125+
126+
defer.resolve( 2 );
127+
128+
piped.done(function( value ) {
129+
assert.strictEqual( this, piped,
130+
"default context gets updated to latest promise in the chain" );
131+
assert.strictEqual( value, 6, "proper value received" );
132+
done.pop().call();
133+
});
134+
135+
defer2 = jQuery.Deferred();
136+
piped2 = defer2.pipe();
137+
138+
defer2.resolve( 2 );
139+
140+
piped2.done(function( value ) {
141+
assert.strictEqual( this, piped2,
142+
"default context updated to latest promise in the chain (without passing function)" );
143+
assert.strictEqual( value, 2, "proper value received (without passing function)" );
144+
done.pop().call();
145+
});
146+
});
147+
148+
test( "isResolved() and isRejected()", function( assert ) {
149+
150+
assert.expect( 12 );
151+
152+
var defer = jQuery.Deferred();
153+
154+
expectWarning( "isResolved unresolved", function() {
155+
assert.strictEqual( defer.isResolved(), false, "isResolved pending" );
156+
});
157+
158+
expectWarning( "isRejected unresolved", function() {
159+
assert.strictEqual( defer.isRejected(), false, "isRejected pending" );
160+
});
161+
162+
defer.resolve( 1 );
163+
164+
expectWarning( "isResolved resolved", function() {
165+
assert.strictEqual( defer.isResolved(), true, "isResolved resolved" );
166+
});
167+
168+
expectWarning( "isResolved resolved", function() {
169+
assert.strictEqual( defer.isRejected(), false, "isRejected resolved" );
170+
});
171+
172+
defer = jQuery.Deferred().reject( 1 );
173+
174+
expectWarning( "isResolved resolved", function() {
175+
assert.strictEqual( defer.isResolved(), false, "isResolved rejected" );
176+
});
177+
178+
expectWarning( "isResolved resolved", function() {
179+
assert.strictEqual( defer.isRejected(), true, "isRejected rejected" );
180+
});
181+
});

test/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
<script src="ajax.js"></script>
4242
<script src="event.js"></script>
4343
<script src="traversing.js"></script>
44+
<script src="deferred.js"></script>
4445
</head>
4546
<body>
4647
<div id="qunit"></div>

warnings.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,19 @@ $(document).ajaxStart(function(){ $("#status").text("Ajax started"); });
148148

149149
**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*.
150150

151+
### JQMIGRATE: deferred.pipe() is deprecated
152+
153+
**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.
154+
155+
**Solution**: In most cases it is sufficient to change all occurrences of `.pipe()` to `.then()`. Ensure that you aren't relying on context/state propagation (e.g., using `this`) or synchronous callback invocation, which were dropped from `.then()` for Promises/A+ interoperability as of jQuery 3.0.
156+
157+
### JQMIGRATE: deferred.isResolved() is deprecated
158+
### JQMIGRATE: deferred.isRejected() is deprecated
159+
160+
**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.
161+
162+
**Solution**: To determine the state of a Deferred object, call `deferred.state()` and check for a `"resolved"` or `"rejected"` string values.
163+
151164
### JQMIGRATE: jQuery.clean() is deprecated
152165

153166
**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.

0 commit comments

Comments
 (0)