如何在2次连续角度服务呼叫期间中止/取消第一次呼叫的承诺?

时间:2016-04-19 04:30:22

标签: javascript angularjs

当在下拉项目选择中通过$ http角度服务进行2次连续服务呼叫并且假设第一次呼叫花费时间返回并且在第一次呼叫解决之前第二次呼叫返回时,则它显示第一次呼叫的第二次呼叫数据。

如果在第一次通话解决之前再次进行服务呼叫,那么有没有办法中止第一次承诺。

为了演示目的,我创建了样本plunkar,其中包含少量项目的下拉列表,我添加了明确的条件,在选择第一项时,它花费的时间比其他项目少一些。 因此,选择第一项并立即选择第二项以重现场景,检查屏幕上显示的收藏书。

任何帮助表示赞赏!

服务代码:

app.factory('bookService', function($http, $q, $timeout) {
  return {
    getBook: function(id) {
      var promise = $q.defer();
      var timeoutSpan = id == 1 ? 3000 : 500;
      $http.get("favouriteBooks.json").success(function(data) {
        $timeout(function() {
          promise.resolve(data.filter(function(obj) {
            return obj.id == id
          }));
        }, timeoutSpan);
      }).error(function(msg) {
        promise.reject(msg);
      })
      return promise.promise;
    }
  }
});

2 个答案:

答案 0 :(得分:1)

我找到了两种方法来处理这种情况 -

案例1:在服务级别创建全局$ q deffer对象,并在调用$ http请求之前检查此对象是否具有值。如果此deffer对象具有值,则显式解析它。 Plunkar代码 - code snippet

服务代码:

app.factory('bookService', function($http, $q, $timeout, bookConstants) {
  var service = {};
  service.mypromise = null;

  service.getBook = function(id) {
    if (service.mypromise) {
      service.mypromise.resolve(bookConstants.EXPLICIT_CANCEL);
      service.mypromise = null;
    }
    service.mypromise = $q.defer();
    var timeoutSpan = id == 1 ? 3000 : 500;
    $http.get("favouriteBooks.json").success(function(data) {
      $timeout(function() {
        if (service.mypromise) {
          service.mypromise.resolve(data.filter(function(obj) {
            service.mypromise = null;
            return obj.id == id
          }))
        }
      }, timeoutSpan);
    }).error(function(msg) {
      service.mypromise.reject(msg);
    })
    return service.mypromise.promise;
  }

  return service;

});

案例2:将$ q deffer对象作为服务响应返回并将其维持在控制器级别。并且在连续服务呼叫首先检查并明确解决第一个服务呼叫然后继续其他服务呼叫的情况下。 Plunkar代码 - code snippet

示例代码:

$scope.getSelectedValue = function() {
    var id = $scope.selitem.id
    $scope.cancel();
    var bookPromise = bookService.getBook(id);
    $scope.requests.push(bookPromise);
    bookPromise.promise.then(getBookSuccess)
      .catch(errorCallback)
      .finally(getBookComplete);
  }

  function getBookSuccess(favouriteBooks) {
    if (favouriteBooks == 'User Cancelled') {
      return;
    }

    var books = '';
    angular.forEach(favouriteBooks, function(book) {
      books += book.bookName + ' '
    });

    $scope.selectedvalues = 'Name: ' + $scope.selitem.name +
      ' Id: ' + $scope.selitem.id + ' Favourite Book(s): ' + books;
  }

  function errorCallback(errorMsg) {
    console.log('Error Message: ' + errorMsg);
  }

  function getBookComplete() {
    console.log('getBook Has Completed!');
  }

  $scope.cancel = function() {
    if ($scope.requests) {
      angular.forEach($scope.requests, function(request) {
        request.resolve('User Cancelled');
        clearRequest(request);
      })
    }
  };

  var clearRequest = function(request) {
    $scope.requests.splice($scope.requests.indexOf(request), 1);
  };

}]);

app.factory('bookService', function($http, $q, $timeout) {
  var service = {};
  service.getBook = function(id) {
    var promise = $q.defer();
    var timeoutSpan = id == 1 ? 3000 : 500;
    $http.get("favouriteBooks.json").success(function(data) {
      $timeout(function() {
        promise.resolve(data.filter(function(obj) {
          return obj.id == id
        }))
      }, timeoutSpan);
    }).error(function(msg) {
      promise.reject(msg);
    })
    return promise;
  }
  return service;
});

答案 1 :(得分:-1)

您可以使用以下内容等待两个或多个承诺$q.all([promise1,promise2]).then(function(data){....});

要访问第一个承诺的数据,只需使用data[0],第二个承诺返回值将保存在data[1]中,依此类推......