如果这是一个愚蠢的问题,请原谅我。我已经尝试了几个小时,而我的大脑却刚刚停止工作。
我有这样的系统,它包含三个AJAX调用。服务器首次 call 的响应通常为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页面和用于调试的基本服务器支持。
当我单击页面上的唯一按钮时,第一个查询返回成功,第二个查询按预期失败。当我第二次单击该按钮时,第一个查询将跳过,因为上次成功,第二次再次失败,这也是预期的。
这里的问题是:
我使用
resetDfr
方法之前的dfr
可以解析或拒绝,但它不再对resolve
和reject
方法作出反应。 resetDfr
方法时,dfr
可以再次得到解决或拒绝,但是旧dfr
的回调未与新的dfr
对象绑定(bind),并且我找不到将旧的回调克隆到新的dfr
的方法。 您对我在这里想要完成的工作有何建议?
最佳答案
promise 表示受时间限制的单个值。从概念上讲,您不能“重用”或推迟重设-一旦过渡,它便会停留。有些构造将对多个值的 promise 概括化(例如可观察到的),但是在这种情况下,它们会更复杂-每个请求只使用一个延迟的构造可能会更好。
jQuery的AJAX已经提供了promise接口(interface)。您的代码大部分都是多余的-您可以并且应该考虑使用现有的工具。
让我们看看$.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
等来解开结果。也很可能也可以在单个链中执行此操作(但是,如果您未明确指定,则无法访问以前的值)保存。记录下来-这根本不是一个愚蠢的问题:)