取消以前由 ng-change 创建的 api 请求

Cancelling previous api requests created by ng-change

本文关键字:api 请求 创建 ng-change 取消      更新时间:2023-09-26

我有一个搜索框附加到角度控制器中的函数,用于调用Web服务以获取人员列表:

        <div class="input-group">
            <div class="input-group-addon">Find Person</div>
            <input type="text" class="form-control" placeholder="Search" ng-change="vm.getPeople()" ng-model="vm.searchTxt" ng-model-options="{debounce: 500}"/>
        </div>

它具有去抖动功能,不会发出太多呼叫。

该函数如下所示:

    function getPeople() {
        vm.spinner = true;
        peopleClient
            .get({
                GenSearchTerm: vm.searchTxt
            })
            .success(function (data) {
                vm.spinner = false;
                vm.searchResult = data.results;
            })
            .error(function (err) {
                vm.spinner = false;
                log.debug(err);
                err;
            });
    }

这按预期工作,但存在问题。如果我输入一个非常松散的术语,返回许多结果,然后一个非常具体的术语返回,例如,1 个结果(即"a"然后"Angela Smith"),数据将首先返回特定术语,然后在执行回调时替换通用术语(这是第一个,但在服务器端花费的时间更长。是的,服务器端调用太慢了,我会考虑在那里修复它,但我也想更好地处理它在客户端。

那么,如果我知道以后的调用取代了此函数创建的任何正在进行的请求,我该如何停止/取消它们?

编辑:

太棒了,这让我明白了一个很好的观点,并且有使用超时的很好的例子。想看看是否有人可以告诉我这个简单的添加是否有问题。它在功能上工作,但不确定我是否很好地处理了承诺。

function getPeople() {
    vm.spinner = true;

    //check for existing 
    if (vm.searchPromise) {
        //cancel the existing call 
        vm.searchPromise.resolve(); 
    }
    vm.searchPromise = $q.defer();
    peopleClient
        .get({
            GenSearchTerm: vm.searchTxt
        }, vm.searchPromise)
        .success(function (data) {
            vm.spinner = false;
            vm.searchResult = data.results;
        })
        .error(function (err) {
            vm.spinner = false;
            log.debug(err);
            err;
        });
}

然后在人民客户中:

    function get(params, deferred) {
        return $http.get(url + 'people', {
            headers: {
                Authorization: 'Bearer ' + access_token
            },
            params: params,
            timeout: deferred.promise
        });
    }

如果您使用的是 restangular,则可以使用 timeout : requestCancelDeferred

var requestCancelDeferred = $q.defer();

然后,当您需要取消请求时:

requestCancelDeferred.resolve();

您的查询:

return Restangular
    .one('homes')
    .withHttpConfig({ timeout : requestCancelDeferred.promise })
    .get(/*your query here*/);

或使用$http(版本1.1.5+):

var requestCancelDeferred = $q.defer();
$http.get('/someUrl', {timeout: requestCancelDeferred.promise}).success(successCallback);

当您需要取消时:

requestCancelDeferred.resolve();

如果您将服务工厂与$resource请求一起使用,则可以执行以下操作:

app.factory("peopleClient", function($http, $q) {
    var canceller = $q.defer();
    return $resource(url, options || {}, {
        'get': {
            method: 'GET',
            timeout: canceller.promise
        }
    });
});