AngularJS中如何按顺序执行嵌套$http.get请求?
Ah, I've run into this exact problem with AngularJS's asynchronous $http calls before—let me walk you through what's going wrong and how to fix it.
The Root Cause
The core issue here is that $http requests are asynchronous. When you loop through the first request's results and fire off a second $http.get for each item, the loop doesn't wait for each request to finish before moving on. By the time you try to use $scope.infoWithStatus, most (if not all) of those second requests are still in flight, leaving your array empty or only partially populated.
The Solution: Use $q.all to Coordinate Async Requests
AngularJS provides the $q service to manage Promises, which lets us wait for all our second requests to complete before assembling the final array. Here's how to adjust your code:
First, make sure you inject $q into your controller (along with $scope and $http). Then update your populateData function:
$scope.populateData = function() { $scope.infoWithStatus = []; // First request to get names $http.get("commonAppGet.jsp?sqlStr=select name from test where title_id=1") .then(function(resp) { const nameList = resp.data; // Create an array of Promises for each status request const statusPromises = nameList.map(function(name) { return $http.get(`commonAppGet.jsp?sqlStr=select status from test_status where name='${name}'`) .then(function(statusResp) { // Return the combined object we want for each item return { name: name, status: statusResp.data[0].status }; }); }); // Wait for all status requests to complete return $q.all(statusPromises); }) .then(function(allResults) { // All requests are done—assign the full array to scope $scope.infoWithStatus = allResults; console.log("All data loaded successfully:", $scope.infoWithStatus); }) .catch(function(error) { // Handle any errors from either request console.error("Request failed:", error); }); };
How This Works
- Map instead of ForEach: We use
mapto transform each name into a Promise (from the second$httpcall). This gives us an array of Promises we can track. $q.allfor Coordination:$q.all(statusPromises)waits until every Promise in the array resolves. Once they do, it passes an array of all resolved values (our combined name+status objects) to the next.then()callback.- Guaranteed Full Population: By the time we assign
allResultsto$scope.infoWithStatus, every second request has finished, so your array is complete and ready to use.
Bonus Tips
- Parallel Efficiency: This approach runs all second requests in parallel, which is much faster than running them one after another. If you need sequential execution (e.g., due to backend rate limits), you can chain Promises instead, but parallel is almost always preferable here.
- Security Alert: Directly concatenating
nameinto your SQL string is a critical SQL injection vulnerability! Modify your backend to accept parameters safely, and pass the name as a request parameter instead of embedding it insqlStr. For example:
Let your backend handle parameterizing the query to avoid attacks.$http.get("commonAppGet.jsp", { params: { query: "select status from test_status where name=?", nameParam: name } })
内容的提问来源于stack exchange,提问作者Nishant Singh

