当通过 $http Angular 服务对下拉项选择进行 2 个连续的服务调用时,假设第一个调用需要时间返回,第二个调用在第一个调用解析之前返回,那么它会显示第二个项目选择的第一次调用的数据。
如果在第一次调用解决之前再次进行服务调用,是否有任何方法可以中止第一个 promise 。
出于演示目的,我创建了示例 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;
}
}
});
最佳答案
我找到了两种方法来处理这种情况 -
情况 1: 在服务级别创建全局 $q defer 对象,并在调用 $http 请求之前检查该对象是否有值(value)。如果此延迟对象具有值,则显式解析它。普伦卡代码 - 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 defer 对象作为服务响应并在 Controller 级别维护它。如果是连续的服务调用,请首先检查并明确解决第一个服务调用,然后继续处理其他服务调用。 普伦卡代码 - 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;
});
关于javascript - 如何在连续 2 个 Angular 服务调用期间中止/取消第一次调用的 promise ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36708581/