新 $.带有旧回调的延迟对象
New $.Deferred object with the old callbacks
如果这是一个愚蠢的问题,请原谅我。我已经尝试了几个小时,我的大脑刚刚停止工作。
我有这样一个系统,它由三个 AJAX 调用组成。第一次调用的服务器响应通常是 200 成功;但是第二个和第三个查询很脆弱,因为它们是图像上传,而在服务器端,我有太多的验证规则,以至于客户端的图像大多失败。
window.AjaxCall = function () {
// to pass to $.ajax call later
this.args = arguments;
// xhr status
this.status = null;
// xhr results (jqXHR object and response)
this.xhrResponse = {};
this.dfr = new $.Deferred();
// to provide an easier interface
this.done = this.dfr.done;
this.fail = this.dfr.fail;
this.then = this.dfr.then;
};
AjaxCall.prototype.resetDfr = function () {
this.dfr = new $.Deferred();
};
AjaxCall.prototype.resolve = function () {
this.dfr.resolve(
this.xhrResponse.result,
this.xhrResponse.jqXHR
);
this.resetDfr();
};
AjaxCall.prototype.reject = function () {
this.dfr.reject(
this.xhrResponse.jqXHR
);
this.resetDfr();
};
AjaxCall.prototype.query = function () {
var _this = this;
// if query hasn't run yet, or didn't return success, run it again
if (_this.status != 'OK') {
$.ajax.apply(_this, _this.args)
.done(function (result, textStatus, jqXHR) {
_this.xhrResponse.result = result;
_this.xhrResponse.jqXHR = jqXHR;
_this.resolve();
})
.fail(function (jqXHR) {
_this.xhrResponse.jqXHR = jqXHR;
_this.reject();
})
.always(function (a, b, c) {
var statusCode = (typeof c !== 'string'
? c
: a).status;
if (statusCode == 200) {
_this.status = 'OK';
}
});
}
// if query has been run successfully before, just skip to next
else {
_this.resolve();
}
return _this.dfr.promise();
};
AjaxCall
类如上所示,我像这样连续三次调用:
var First = new AjaxCall('/'),
Second = new AjaxCall('/asd'),
Third = new AjaxCall('/qqq');
First.then(function () {
console.log('#1 done');
}, function() {
console.error('#1 fail');
});
Second.then(function () {
console.log('#2 done');
}, function() {
console.error('#2 fail');
});
Third.then(function () {
console.log('#3 done');
}, function() {
console.error('#3 fail');
});
var toRun = function () {
First.query()
.then(function () {
return Second.query();
})
.then(function () {
return Third.query()
});
};
$('button').click(function () {
toRun();
});
这些代码位于测试环境中。通过测试环境,我的意思是一个简单的HTML页面和基本的服务器支持调试。
- 主页 (/) 始终返回 200 成功。
- /asd 前 3 次返回 404 未找到,200 成功一次作为模式返回(即三个 404 ->一个 200 ->三个 404 ->一个 200 ->三个 404 -> ... )。
- /qqq 始终返回 404 未找到。
当我单击页面上的唯一按钮时,第一个查询返回成功,第二个查询按预期失败。当我第二次单击该按钮时,第一个查询跳过,因为它上次成功,第二个查询再次失败,也如预期的那样。
这里的问题是:
- 在我使用
resetDfr
方法之前,因为dfr
已解析或拒绝,它不再对resolve
和reject
方法做出反应。 - 当我以示例中所示的方式调用
resetDfr
方法时,dfr
能够再次解决或拒绝,但旧dfr
的回调未与新dfr
对象绑定,我找不到将旧回调克隆到新dfr
的方法。
你有什么建议来完成我在这里要做的事情?
承诺表示受时间约束的单个值。你不能在概念上"重用"一个延迟的或重置它 - 一旦它过渡它就会坚持下去。有一些构造可以将承诺推广到多个值(如可观察量),但在这种情况下这些结构更复杂 - 最好只使用每个请求的一个延迟。
jQuery的AJAX已经提供了一个promise接口。您的代码大多是多余的 - 您可以并且应该考虑使用现有的工具。
让我们看看$.get
:
- 它已经返回了一个承诺,因此您无需创建自己的延期。
- 它已经使用了浏览器缓存,除非您的服务器禁止 HTTP 缓存或浏览器拒绝它,否则只会在到达正确的响应后向服务器发出一个请求(假设您没有显式将
{cache: false}
传递给其参数。
如果发出 post 请求,您可以使用 $.post
或更一般的$.ajax
用于任意选项。
您的代码大致如下所示:
$("button").click(function(){
var first = $.get("/");
var second = first.then(function(){
return $.get("/asd");
});
var third = second.then(function(){
return $.get("/qqq");
});
});
我将它们放在变量中的原因是,以便您以后可以通过执行first.then
等操作自己解包结果。在单个链中也很有可能执行此操作(但是如果您不显式保存以前的值,您将无法访问以前的值。
为了记录 - 这根本不是一个愚蠢的问题:)
相关文章:
- 使用jquery延迟对象链接多个ajax调用
- jQuery通过嵌套的ajax调用延迟对象
- $.ajax延迟对象
- 在延迟对象解析后执行启用函数
- 延迟对象在解析之前返回
- 是否有任何方法可以像处理jQuery中附加到XHR延迟对象的done方法处理程序一样处理websocket onmess
- 使用 jQuery 延迟对象管理 ajax 调用
- jquery延迟对象回调未触发
- 在 jQuery 的延迟对象中抛出错误
- 新 $.带有旧回调的延迟对象
- jQuery:在成功/错误中使用延迟对象(ajaxSetup 选项)
- 将延迟对象作为失败返回
- 具有延迟对象的构造函数
- 使用 jQuery 延迟对象以串行方式处理 jQuery 集合/数组
- 一个接一个的 Div 动画使用延迟对象
- 如何排列 jQuery 延迟对象
- 如何使与jquery延迟对象一起工作的函数表现得像同步函数
- AngularJS-如何从图像对象创建延迟对象
- 异步地理定位API和jQuery延迟对象
- 使用延迟对象/承诺的Ajax调用返回失败