【发布时间】:2014-12-30 14:22:13
【问题描述】:
如果这是一个愚蠢的问题,请原谅我。我已经尝试了几个小时,但我的大脑刚刚停止工作。
我有这样一个由三个 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 页面和用于调试的基本服务器支持。
- 主页 (/) 始终返回 200 成功。
- /asd 返回 404 Not Found,前 3 次 和 200 Success 一次作为模式(即三个 404 -> 一个 200 -> 三个 404 -> 一个 200 -> 三个 404 -> ...)。
- /qqq 一直返回404 Not Found。
当我单击页面上的唯一按钮时,第一个查询返回成功,第二个查询按预期返回失败。当我第二次单击该按钮时,第一次查询跳过,因为它上次成功,第二次再次失败,也如预期的那样。
这里的问题是:
-
在我使用
resetDfr方法之前,因为dfr已经解决或拒绝,它不再对resolve和reject方法作出反应。 -
当我以示例中的方式调用
resetDfr方法时,dfr能够再次被解析或拒绝,但旧dfr的回调没有与新的dfr对象,我找不到将旧回调克隆到新的dfr的方法。
你有什么建议来完成我在这里尝试做的事情?
【问题讨论】:
-
从问题中实际上并不清楚您要达到什么目标。我明白你想克隆 deferred 的回调。但是为了什么?您想在每次点击时重新运行所有请求吗?为什么这些请求应该按顺序而不是并行运行?
-
@YuryTarabanko 请求必须是连续的,因为在实际产品中,第一个查询将表单字段保存到数据库表中,并使用 ID 进行响应。正在使用该 ID 发送其他查询。我确实想重新运行请求如果它们之前失败。当用户发送请求并且服务器说它失败时,我会警告用户失败,以便他们可以相应地更改输入(图像),然后重试。
标签: javascript jquery promise jquery-deferred