Jquery 如何将所有处理程序从一个转移到另一个?
假设我有一个Jquery 如何将所有处理程序从一个转移到另一个?,jquery,promise,jquery-deferred,Jquery,Promise,Jquery Deferred,假设我有一个$.Deferred和一个jqXHR对象。是否有一种方法可以将所有绑定到deferred(然后,总是,done,fail)的处理程序转移到XHR对象(据我所知,它是deferred的扩展) 以下是我的想法: $.ajaxOne = function(options) { var xhr = null; return function() { if(xhr) xhr.abort(); xhr = $.ajax(options).alwa
$.Deferred
和一个jqXHR
对象。是否有一种方法可以将所有绑定到deferred(然后,总是,done,fail)的处理程序转移到XHR对象(据我所知,它是deferred的扩展)
以下是我的想法:
$.ajaxOne = function(options) {
var xhr = null;
return function() {
if(xhr) xhr.abort();
xhr = $.ajax(options).always(function() {
xhr = null;
});
}
}
我想创建一个函数,类似于$.ajax
,只是如果您快速连续多次调用它,它将中止最后一个请求,只完成最近一个请求。这在许多需要验证用户输入的场景中非常有用
例如,您可能希望检查是否使用了用户名,但如果在您启动ajax调用后,他们再次开始在用户名字段中键入用户名,则您不关心最后的结果,只关心最近的结果
此外,我认为请求不能保证以与发出请求相同的顺序返回(我想这取决于您的服务器设置),因此您也可能会遇到同步问题
无论如何,上面代码的问题在于,因为它返回一个函数,所以可以随时执行ajax调用,但不能将完成处理程序绑定到它。因此,我必须以某种方式混合延迟处理程序,并将它们重新绑定到XHR对象。得出了以下结论:
function AjaxOne(options) {
this.options = options;
this._xhr = null;
this._always = [];
this._success = [];
this._fail = [];
};
$.extend(AjaxOne.prototype, {
always: function(cb) {
this._always.push(cb);
return this;
},
done: function(cb) {
this._success.push(cb);
return this;
},
fail: function(cb) {
this._fail.push(cb);
return this;
},
then: function(success, fail) {
this._success.push(success);
this._fail.push(fail);
return this;
},
run: function(options) {
if(this._xhr) {
this._xhr.abort();
}
this._xhr = $.ajax($.extend({},options,this.options,{context:this}))
.always(function() {
this._xhr = null;
for(var i=0; i<this._always.length;++i) this._always[i].apply(this,arguments);
})
.done(function() {
for(var i=0; i<this._success.length;++i) this._success[i].apply(this,arguments);
})
.fail(function() {
for(var i=0; i<this._fail.length;++i) this._fail[i].apply(this,arguments);
});
}
});
函数AjaxOne(选项){
this.options=选项;
这是.\u xhr=null;
这个;
这就是成功;
这个。_fail=[];
};
$.extend(AjaxOne.prototype{
始终:功能(cb){
这个。总是。推(cb);
归还这个;
},
完成:功能(cb){
这是成功推送(cb);
归还这个;
},
失败:功能(cb){
这是失败的推送(cb);
归还这个;
},
然后:功能(成功,失败){
这是成功;
这个.\u fail.push(失败);
归还这个;
},
运行:功能(选项){
如果(这个){
这是。xhr.abort();
}
this.xhr=$.ajax($.extend({},options,this.options,{context:this}))
.always(函数(){
这是.\u xhr=null;
对于(var i=0;i
我没有使用延迟对象就实现了。
keyup事件-
$("#uID").keyup(function () {
console.log("KeyUp")
var textElement = this;
clearTimeout(textElement.timer);
if(textElement.xhrReq && textElement.xhrReq.abort){
textElement.xhrReq.abort();
}
textElement.timer = setTimeout(function(){
console.log("Invoking validation : " + textElement.value);
validateUID(textElement);
}, 1000);
});
在validateUID()中,我已将整个XHR对象分配给输入元素的属性-
textElement.xhrReq = $.ajax({
...
});
有一个缺点——我承认这一点——我们需要将整个XHR对象保留在元素中
假设我有一个$.Deferred和一个jqXHR对象。有没有办法将绑定到Deferred(然后,总是,完成,失败)的所有处理程序转移到XHR对象(据我所知,它是Deferred的扩展)
或多或少,是的,但不是以您期望的方式。您不需要“移动处理程序”,而只需使用XHR延迟来解析延迟的(有处理程序的)。这将使延迟采用ajax承诺的状态,或者不采用,因为jQuery不兼容。因此您需要手动将触发器作为处理程序放置:
var deferred = $.Deferred(),
xhr = $.ajax(…);
xhr.done(deferred.resolve).fail(deferred.reject).progress(deferred.notify);
但是,不鼓励这样使用,只要在需要时使用xhr
,它们是相等的。或者使用xhr.then()
创建一个全新的promise对象,其解析方式与xhr
的解析方式完全相同
无论如何,上面代码的问题是,因为它返回一个函数,所以您可以随时执行ajax调用,但不能将完成处理程序绑定到它。因此,我必须以某种方式混合延迟处理程序,并将它们重新绑定到XHR对象
您仍然可以从返回的函数中返回每个xhr
对象,并将处理程序绑定到该对象。如果中止,将调用其error
处理程序
$.ajaxOne = function(options) {
var xhr = null;
return function(name) {
options.data = name;
if (xhr) xhr.abort();
return xhr = $.ajax(options).always(function() {
// ^^^^^^
xhr = null;
});
}
}
var checkUserAccount = $.ajaxOne({…});
$input.keyup(function(e) {
checkUser(this.value).done(function(ajaxResult) {
// do anything here with the ajaxResult from the latest call
// if there was another keyup event, this callback never fires
});
});
此外,我认为请求不能保证以与发出请求相同的顺序返回(我想这取决于您的服务器设置),因此您也可能会遇到同步问题
如果再次调用函数时对每个旧的请求调用abort
,则不会这样做-这将保持不变,即一次最多只有一个活动的ajax请求
我想创建一个类似于$.ajax的函数,只是如果您快速连续多次调用它,它将中止最后一个请求,只完成最近一个请求
听起来很像一个事件流。你会想看看函数式反应式编程!我认为这是不可能的…为什么不使用jqXHR回调解析延迟的函数…xhr.done(function(){deferred.resolveWith.apply(deferred,arguments);})。fail(function(){deferred.rejectWith.apply)(延迟,参数);})
出于好奇,为什么要进行这种设置?为什么不直接使用jqXHR对象,而不是创建一个新的$。延迟的?另外,在您的解决方案中,您希望最终解决延迟的问题还是不解决延迟的问题?@RocketHazmat:在这个特定的场景中,我基本上希望在不立即执行的情况下构建一个“ajax”对象。因此,我考虑返回一个延迟的,这样用户仍然可以将他们的事件绑定到它,然后当他们执行它时,它将运行ajax调用…如果您愿意,我将发布一个更具体的示例,我承认我没有充分考虑它:-)@RocketHazmat:我实际上是将它与去Bouncing结合使用。我去Bouncing大约300毫秒,但是如果AJAX需要很长时间才能返回,它仍然会触发两次。我可以延迟执行新的AJAX调用,直到最后一个调用返回,但这会提供较差的用户体验……调用可能会堆积起来,他们会等待一段时间等待最新结果的时间太长了。@RocketHazmat:我不知道你的$如何。延迟的示例将如何工作……你没有将任何东西绑定到$。ajax
--只有该对象知道调用何时返回。我认为Arun是目前为止最好的解决方案。不,请不要这样做。你的方法已被破坏,你的AjaxOne
应确定实例