如何在 AngularJS 控制器中发出同步 AJAX 请求
How to make synchronous AJAX requests in AngularJS controller
有人告诉我 Angular 中的 $http 是异步的。但是,出于某种目的,我需要发出顺序 AJAX 请求。
我想从文件列表中读取所有文件,然后从所有这些文件中获取编号。例如:
"fileNames"的内容:
file1
file2
"file1"的内容:
1
"file2"的内容:
2
下面的代码会计算总和
<!DOCTYPE html>
<html>
<body>
<p id="id01"></p>
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<script>
var fileString;
/* first AJAX call */
$.ajax({
url: 'fileNames', type: 'get', async: false,
success: function(content) {
fileString = content;
}
});
var fileList = fileString.split('\n');
var sum = 0;
for (var i = 0; i < fileList.length; i++) {
/* second AJAX call in getNumber function */
sum += getNumber(fileList[i]);
}
document.getElementById("id01").innerHTML = sum;
function getNumber(file) {
var num;
$.ajax({url: file, type: 'get', async: false,
success: function(content) {
num = content;
}
});
return parseInt(num);
}
</script>
</body>
</html>
由于这两个$.ajax调用是顺序的,我不知道如何在AngularJS中实现这个功能。比如说,最后,我想要 $scope.sum = 1 + 2.
有人可以在 AngularJS 中使用它吗?一些简单的代码将不胜感激!
您可以使用承诺和承诺链接(使用 $q
和 $http
返回的承诺)。示例:在您的控制器中,您可以这样做(在注入 $http
, $q
之后):
angular.module('myApp').controller('MyCtrl', ['$http','$q','$scope', function($http, $q, $scope){
function getData(){
//return promise from initial call
return $http.get('fileNames')
.then(processFile) //once that is done call to process each file
.then(calculateSum);// return sum calculation
}
function processFile(response){
var fileList = response.data.split('\n');
//Use $q.all to catch all fulfill array of promises
return $q.all(fileList.map(function(file){
return getNumber(file);
}));
}
function getNumber(file) {
//return promise of the specific file response and converting its value to int
return $http.get(file).then(function(response){
return parseInt(response.data, 10);
});
//if the call fails may be you want to return 0? then use below
/* return $http.get(file).then(function(response){
return parseInt(response.data, 10);
},function(){ return 0 });*/
}
function calculateSum(arrNum){
return arrNum.reduce(function(n1,n2){
return n1 + n2;
});
}
getData().then(function(sum){
$scope.sum = sum;
}).catch(function(){
//Oops one of more file load call failed
});
}]);
另见:
- $http
- $q
- $q.all
- Array.map - 您也可以手动遍历数组并将 promise 推送到数组。
- Array.reduce - 你也可以遍历数字并将它们相加。
这并不意味着调用是同步的,但它们是异步的,并且仍然以更高效且易于管理的方式执行您需要的操作。
您可以使用由 $http 方法调用return编辑的承诺:
//Do some request
$http.get("someurl")
//on resolve call processSomeUrlResponse
.then(processSomeUrlResponse)
//then do another request
.then(function(){
return $http.get("anotherurl").then(processAnotherUrlResponse);
})
//when previous request is resolved then do another
.then(function(){
return $http.get("yetanotherurl").then(processYetAnotherUrlResponse);
})
//and do another
.then(function(){
return $http.get("urls").then(processUrlResponse);
});
当您在 then
回调中 return 承诺时,下一个 then
将不会被调用,直到承诺已解决。
angular 使用承诺的 http 函数是可能的。例如:
$scope.functionA = function(){
return $q(function(resolve){
resolve("theAnswertoallquestions");
});
}
$scope.functionB = function(A){
return $q(function(resolve);
$http.get("URLRoot/" + A).success(function(){resolve();});
});
}
$scope.functionC = function(){
return $q(function(resolve);
resolve("I AM THE LAST TO EXEGGCUTE!!!");
});
}
$scope.allTogetherNow = function(){
var promise = $scope.functionA();
promise.then(function(A){
return $scope.functionB(A);
}).then(function(){
return $scope.functionC();
}).then(function(){
return "ALL DONE"
});
}
$scope.allTogetherNow();
其他答案显示了如何使用 promises 或所谓的链接以异步方式正确使用 $http,这是使用 $http 的正确方法。
按照您的要求尝试同步执行此操作将阻止控制器的循环,这是您永远不想做的事情。
您仍然可以执行循环检查承诺状态的糟糕操作。这可以通过 promise 的 $$state
属性 来完成,它有一个名为 status
的 属性
有人告诉我 Angular 中的 $http 是异步的。但是,出于某种目的,我需要发出顺序 AJAX 请求。 我想从文件列表中读取所有文件,然后从所有这些文件中获取编号。例如:
"fileNames"的内容:
file1
file2
"file1"的内容:
1
"file2"的内容:
2
下面的代码会计算总和
<!DOCTYPE html>
<html>
<body>
<p id="id01"></p>
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<script>
var fileString;
/* first AJAX call */
$.ajax({
url: 'fileNames', type: 'get', async: false,
success: function(content) {
fileString = content;
}
});
var fileList = fileString.split('\n');
var sum = 0;
for (var i = 0; i < fileList.length; i++) {
/* second AJAX call in getNumber function */
sum += getNumber(fileList[i]);
}
document.getElementById("id01").innerHTML = sum;
function getNumber(file) {
var num;
$.ajax({url: file, type: 'get', async: false,
success: function(content) {
num = content;
}
});
return parseInt(num);
}
</script>
</body>
</html>
由于这两个$.ajax调用是顺序的,我不知道如何在AngularJS中实现这个功能。比如说,最后,我想要 $scope.sum = 1 + 2.
有人可以在 AngularJS 中使用它吗?一些简单的代码将不胜感激!
您可以使用承诺和承诺链接(使用 $q
和 $http
返回的承诺)。示例:在您的控制器中,您可以这样做(在注入 $http
, $q
之后):
angular.module('myApp').controller('MyCtrl', ['$http','$q','$scope', function($http, $q, $scope){
function getData(){
//return promise from initial call
return $http.get('fileNames')
.then(processFile) //once that is done call to process each file
.then(calculateSum);// return sum calculation
}
function processFile(response){
var fileList = response.data.split('\n');
//Use $q.all to catch all fulfill array of promises
return $q.all(fileList.map(function(file){
return getNumber(file);
}));
}
function getNumber(file) {
//return promise of the specific file response and converting its value to int
return $http.get(file).then(function(response){
return parseInt(response.data, 10);
});
//if the call fails may be you want to return 0? then use below
/* return $http.get(file).then(function(response){
return parseInt(response.data, 10);
},function(){ return 0 });*/
}
function calculateSum(arrNum){
return arrNum.reduce(function(n1,n2){
return n1 + n2;
});
}
getData().then(function(sum){
$scope.sum = sum;
}).catch(function(){
//Oops one of more file load call failed
});
}]);
另见:
- $http
- $q
- $q.all
- Array.map - 您也可以手动遍历数组并将 promise 推送到数组。
- Array.reduce - 你也可以遍历数字并将它们相加。
这并不意味着调用是同步的,但它们是异步的,并且仍然以更高效且易于管理的方式执行您需要的操作。
您可以使用由 $http 方法调用return编辑的承诺:
//Do some request
$http.get("someurl")
//on resolve call processSomeUrlResponse
.then(processSomeUrlResponse)
//then do another request
.then(function(){
return $http.get("anotherurl").then(processAnotherUrlResponse);
})
//when previous request is resolved then do another
.then(function(){
return $http.get("yetanotherurl").then(processYetAnotherUrlResponse);
})
//and do another
.then(function(){
return $http.get("urls").then(processUrlResponse);
});
当您在 then
回调中 return 承诺时,下一个 then
将不会被调用,直到承诺已解决。
angular 使用承诺的 http 函数是可能的。例如:
$scope.functionA = function(){
return $q(function(resolve){
resolve("theAnswertoallquestions");
});
}
$scope.functionB = function(A){
return $q(function(resolve);
$http.get("URLRoot/" + A).success(function(){resolve();});
});
}
$scope.functionC = function(){
return $q(function(resolve);
resolve("I AM THE LAST TO EXEGGCUTE!!!");
});
}
$scope.allTogetherNow = function(){
var promise = $scope.functionA();
promise.then(function(A){
return $scope.functionB(A);
}).then(function(){
return $scope.functionC();
}).then(function(){
return "ALL DONE"
});
}
$scope.allTogetherNow();
其他答案显示了如何使用 promises 或所谓的链接以异步方式正确使用 $http,这是使用 $http 的正确方法。 按照您的要求尝试同步执行此操作将阻止控制器的循环,这是您永远不想做的事情。
您仍然可以执行循环检查承诺状态的糟糕操作。这可以通过 promise 的 $$state
属性 来完成,它有一个名为 status