如果这是一个愚蠢的问题,请原谅我。我已经尝试了几个小时,我的大脑刚刚停止工作。
我有这样的系统,包含三个AJAX调用。首次呼叫的服务器响应通常是 200 Success ;但是第二和第三个查询是脆弱的,因为它们是图像上传,而在服务器端,我有很多验证规则,客户的图像大多都失败了。
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页面和基本服务器支持调试。
当我单击页面上的唯一按钮时,第一个查询返回成功,第二个按预期失败。当我第二次单击该按钮时,第一个查询会跳过,因为它上次成功,第二次再次失败,也是预期的。
这里的问题是:
resetDfr
方法之前dfr
已被解决或拒绝,它对resolve
和{{1}没有反应方法了。reject
方法时,resetDfr
能够再次得到解决或拒绝,但是旧的回调{ {1}}未与新dfr
对象绑定,我无法找到将旧回调克隆到新dfr
的方法。你有什么建议来完成我在这里尝试做的事情?
答案 0 :(得分:1)
Promises代表按时间限制的单个值。你无法在概念上重复使用"延迟或重置它 - 一旦它转换它坚持。有些构造将promises概括为多个值(如observables),但在这种情况下这些构造更复杂 - 只使用一个延迟的每个请求可能更好。
jQuery的AJAX 已经提供了一个promise接口。您的代码通常是多余的 - 您可以而且应该考虑使用现有的工具。
让我们看一下$.get
:
{cache: false}
传递给它的参数如果发布帖子请求,您可以使用$.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
等来自行解包结果。很可能在单个链中执行此操作(但是您如果您没有明确保存,则无法访问以前的值。
为了记录 - 它根本不是一个愚蠢的问题:)