我刚遇到一个奇怪的情况,经过一番搜索后无法找到答案。
我有一个文本框,我用它来允许用户键入关键字来过滤表数据。我在输入元素上有一个ng-change
指令,它将触发此代码:
return $http.get(url).then(function (response) {
return response.data;
});
所有这一切都很有效,直到我们的测试人员在IE11中发现了一些不良行为。以下是在IE10中的文本框中键入“M-A-T-T”的示例:
如您所见,每个后续请求的时间都比第一个要长,因此第四个和最后一个请求的结果是控制器接收的请求。
以下是在IE11的文本框中输入“M-A-T-T”的相同示例。
令人费解的是,第二个请求需要大约2秒才能完成,这是在第四个和最后一个请求完成之后。这导致“MA”请求的结果显示当用户期望“MATT”请求的结果时(当前在他们的文本框中)。
如何在Angular中解决这个问题?提前谢谢。
更新 基于冷淡的回应,我实现了以下(除了弹跳之外)非常有效:
var cancelDeferred;
var getUsers = function (criteria) {
if (cancelDeferred) {
cancelDeferred.resolve();
}
cancelDeferred = $q.defer();
return $http.get(url, { timeout: cancelDeferred.promise }).then(function (response) {
cancelDeferred = undefined;
return response.data;
});
};
实际上,主要的挑战是在调用此方法时处理错误。超时会返回错误,就像500会返回错误一样。我想忽略超时并处理实际错误。这是我的解决方案:
function onError(data, status) {
if (data.data !== null && data.status !== 0) {
//handle error
}
}
现在我将尝试弄清楚是否有办法在全球范围内实现此承诺 - 超时,而不必改变大量的$ http.get()调用......
答案 0 :(得分:1)
在$ http的文档中,它讨论了一个配置对象,您可以将其作为第二个参数传递给$ http.get调用,如下所示:
$http.get(url, config);
在该配置中,它讨论了"超时"您可以设置的属性。如果将该属性设置为Promise,那么如果您解析了promise,它将中止请求。查看文档以获取其中的描述。
即使你使用去抖动,你也会想要使用这个"超时"中止请求。
https://docs.angularjs.org/api/ng/service/$http
所以你会做这样的事情:
var cancelDeferred;
function makeRequest(){
if(cancelDeferred) cancelDeferred.resolve(); //when this gets resolved, the previous request will abort.
cancelDeferred = $q.defer();
return $http.get(url,{timeout:cancelDeferred.promise})
.then(function(res){
cancelDeferred = undefined;
return res;
});
}
所以,你将一个promise传递给.get请求,在config对象里面作为" timeout"属性。如果您在响应返回之前解决此延迟,它将中止请求。