Отмена текущих запросов Angular $http при наличии нового запроса

Как отменить текущий запрос Angular $http при новом запросе?

У меня есть приложение Angular с представлением, которое обновляется в режиме реального времени по типу пользователя. Иногда старые запросы завершаются после последнего запроса, то есть в представлении отображаются неверные данные. Какой самый простой способ отменить предыдущий запрос, когда есть новый?

Используя Angular 1.5, для чего это стоит.

<input ng-model = "query" ng-keyup = "search()"/>
{{results | json}}

// In the controller:
    $scope.search = function(){
        $http({
            method: "GET",
            url: "/endpoint.php"
            params: {
                query: $scope.query
            }
        }).then(function(response){
            $scope.results = response.data;
        })
    }

Одно из моих решений:

// In the controller:
    var canceler = $q.resolve();    // New
    $scope.search = function(){
        canceler.resolve("Canceling old request");     // New
        $http({
            method: "GET",
            url: "/endpoint.php"
            params: {
                query: $scope.query
            },
            timeout: canceler.promise    // New
        }).then(function(response){
            $scope.results = response.data;
        })
    }

В этом сценарии, хотя я вызываю canceler.resolve перед запросом $http, запрос появляется как "сбой".

Любые идеи?

изменить: решение найдено!

// In the controller:
    var canceler = $q.defer();

    $scope.search = function(){
        canceler.resolve("cancelled"); // Resolve the previous canceler
        canceler = $q.defer();        // Important: Create a new canceler! 
                                      // Otherwise all $http requests made will fail
        $http({
            method: "GET",
            url: "/endpoint.php"
            params: {
                query: $scope.query
            }
        }).then(function(response){
            $scope.results = response.data;
        })
    }

Ответы

Ответ 1

При запуске нового поиска вызовите функцию cancel(). И вы можете использовать переменную resolved, чтобы убедиться, что вы не прервали свой вызов $http до его запуска. Что-то вроде этого:

var canceler = $q.defer();
var resolved = false;

var cancel = function() {
    canceler.resolve("http call aborted");
};

$scope.search = function() {
    if (resolved) {
        cancel();
    }

    canceler = $q.defer();
    resolved = true;

    $http({
        method: "GET",
        url: "/endpoint.php"
        params: {
            query: $scope.query
        }
        timeout: canceler.promise
    }).then(function(response) {
        $scope.results = response.data;
        resolved = false;
    })
}

Не забудьте ввести $q в свой контроллер/директиву/службу.

Ответ 2

Решение состоит в том, чтобы установить обещание, затем с каждым поиском() отменить его и повторно инициализировать новый. Это будет надежно отменять любые предыдущие $http():

var canceler = $q.defer();

$scope.search = function() {

    canceler.resolve();

    canceler = $q.defer();

    $http({
        method: "GET",
        url: "/endpoint.php"
        params: {
            query: $scope.query
        }
        timeout: canceler.promise
    }).then(function(response) {
        $scope.results = response.data;
    })
}