防止在最近的请求

时间:2015-10-29 19:07:11

标签: javascript angularjs angular-http

我刚遇到一个奇怪的情况,经过一番搜索后无法找到答案。

我有一个文本框,我用它来允许用户键入关键字来过滤表数据。我在输入元素上有一个ng-change指令,它将触发此代码:

return $http.get(url).then(function (response) {
    return response.data;
});

所有这一切都很有效,直到我们的测试人员在IE11中发现了一些不良行为。以下是在IE10中的文本框中键入“M-A-T-T”的示例:

enter image description here

如您所见,每个后续请求的时间都比第一个要长,因此第四个和最后一个请求的结果是控制器接收的请求。

以下是在IE11的文本框中输入“M-A-T-T”的相同示例。

enter image description here

令人费解的是,第二个请求需要大约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()调用......

1 个答案:

答案 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"属性。如果您在响应返回之前解决此延迟,它将中止请求。