我创建了一个 shim,它无缝地添加了取消延迟对象和 ajax 请求的能力。
简而言之,一旦延迟对象被取消,决议/拒绝被完全忽略,并且state
变成“取消”。
根据 jQuery.com 的说法,“一旦对象进入已解决或已拒绝状态,它就会保持该状态。” 因此,一旦延迟对象被解决或拒绝,取消的尝试就会被忽略。
(function () {
originals = {
deferred: $.Deferred,
ajax: $.ajax
};
$.Deferred = function () {
var dfr = originals.deferred(),
cancel_dfr = originals.deferred();
dfr.canceled = false;
return {
cancel: function () {
if (dfr.state() == 'pending') {
dfr.canceled = true;
cancel_dfr.resolve.apply(this, arguments);
}
return this;
},
canceled: cancel_dfr.done,
resolve: function () {
if ( ! dfr.canceled) {
dfr.resolve.apply(dfr, arguments);
return this;
}
},
resolveWith: function () {
if ( ! dfr.canceled) {
dfr.resolveWith.apply(dfr, arguments);
return this;
}
},
reject: function () {
if ( ! dfr.canceled) {
dfr.reject.apply(dfr, arguments);
return this;
}
},
rejectWith: function () {
if ( ! dfr.canceled) {
dfr.rejectWith.apply(dfr, arguments);
return this;
}
},
notify: function () {
if ( ! dfr.canceled) {
dfr.notify.apply(dfr, arguments);
return this;
}
},
notifyWith: function () {
if ( ! dfr.canceled) {
dfr.notifyWith.apply(dfr, arguments);
return this;
}
},
state: function () {
if (dfr.canceled) {
return "canceled";
} else {
return dfr.state();
}
},
always : dfr.always,
then : dfr.then,
promise : dfr.promise,
pipe : dfr.pipe,
done : dfr.done,
fail : dfr.fail,
progress : dfr.progress
};
};
$.ajax = function () {
var dfr = $.Deferred(),
ajax_call = originals.ajax.apply(this, arguments)
.done(dfr.resolve)
.fail(dfr.reject),
newAjax = {},
ajax_keys = [
"getResponseHeader",
"getAllResponseHeaders",
"setRequestHeader",
"overrideMimeType",
"statusCode",
"abort"
],
dfr_keys = [
"always",
"pipe",
"progress",
"then",
"cancel",
"state",
"fail",
"promise",
"done",
"canceled"
];
_.forEach(ajax_keys, function (key) {
newAjax[key] = ajax_call[key];
});
_.forEach(dfr_keys, function (key) {
newAjax[key] = dfr[key];
});
newAjax.success = dfr.done;
newAjax.error = dfr.fail;
newAjax.complete = dfr.always;
Object.defineProperty(newAjax, 'readyState', {
enumerable: true,
get: function () {
return ajax_call.readyState;
},
set: function (val) {
ajax_call.readyState = val;
}
});
Object.defineProperty(newAjax, 'status', {
enumerable: true,
get: function () {
return ajax_call.status;
},
set: function (val) {
ajax_call.status = val;
}
});
Object.defineProperty(newAjax, 'statusText', {
enumerable: true,
get: function () {
return ajax_call.statusText;
},
set: function (val) {
ajax_call.statusText = val;
}
});
// canceling an ajax request should also abort the call
newAjax.canceled(ajax_call.abort);
return newAjax;
};
});
添加后,您可以取消 ajax 调用:
var a = $.ajax({
url: '//example.com/service/'
});
a.cancel('the request was canceled');
// Now, any resolutions or rejections are ignored, and the network request is dropped.
..或一个简单的延迟对象:
var dfr = $.Deferred();
dfr
.done(function () {
console.log('Done!');
})
.fail(function () {
console.log('Nope!');
});
dfr.cancel(); // Now, the lines below are ignored. No console logs will appear.
dfr.resolve();
dfr.reject();