处理ajax个请求的流控(即上一个请求完成后才处理下一个请求)
Flow control of processing ajax requests (i.e. only processing the next request after the previous request has completed)
我已经写了下面的代码,但是在下一个 ajax 调用 result.params.sSessionKey = $scope.sessionKey
之前分配 $scope.sessionKey = data.result;
时遇到问题(是的 result.name=='get_session_key'
评估循环的第一次迭代)。如您所见,我已经尝试使用 $q
,但是所有关于 promises 和 defer 的教程对我来说都没有任何意义(甚至像 this 这样的东西对我没有帮助)。
你能告诉我如何循环 angular.forEach(...
并仅在前一个测试完成后才执行下一个测试吗?
// Angular's implementation of JSON-RPC (as seen here > http://jsfiddle.net/89D4b/1/)
angular.module("JSON-RPC",[]).config([...]);
// Angular
var app = angular.module('testsApp', ['JSON-RPC']);
app.controller('testsCtrl', function($scope, $http, $q) {
// populates the table on startup
$http.get("functions_as_JSON.php")
.success(function(response) {
// store the data locally for angular to loop through
$scope.data = response;
// create a promise for the sessionKey
var defer = $q.defer();
var promise = defer.promise;
promise.then(function(data){
$scope.sessionKey = data.result;
});
////////// AUTO RUN THE TESTS //////////
angular.forEach($scope.data.results,function(value,index){
$scope.runTest(value);
});
});
// test function
$scope.runTest = function(result) {
// (on all but the first test ...)
// if the sessionKey is in the JSON put it in the params to send with the JSON-RPC
if(result.params.sSessionKey) { result.params.sSessionKey = $scope.sessionKey; }
// test the method
$http.jsonrpc($scope.data.endPoint, result.method, result.params)
.success(function(data, status, headers, config) {
// if there are no errors
if (data.error === null && !data.result.status) {
// on the first test the sessionKey gets stored
if(result.name=='get_session_key') {
$scope.sessionKey = data.result;
//defer.resolve(data);
//$scope.$evalAsync(function($scope) { $scope.sessionKey = data.result; });
}
$scope.testSuccess(result, data, status, headers, config);
} else {
$scope.testFailed(result, data, status, headers, config);
}
})
.error(function(data, status, headers, config){ $scope.testFailed(result, data, status, headers, config); });
}
$scope.testSuccess = function(result, data, status, headers, config) {
result.response = {'status':status, 'post':result.params, 'data':JSON.stringify(data)};
result.status_class = 'positive';
result.status = 'success';
}
$scope.testFailed = function(result, data, status, headers, config) {
result.response = {'status':status, 'post':result.params, 'data':JSON.stringify(data)};
result.status_class = 'negative';
result.status = 'failed';
}
});
编辑
我已经修改成如下,还是不行
// Angular's implementation of JSON-RPC (as seen here > http://jsfiddle.net/89D4b/1/)
angular.module("JSON-RPC",[]).config([...]);
// Angular
var app = angular.module('testsApp', ['JSON-RPC']);
app.controller('testsCtrl', function($scope, $http, $q, $timeout) {
// populates the table on startup
$http.get("limesurvey_api_functions_as_JSON.php")
.success(function(response) {
// store the data locally for angular to loop through
$scope.data = response;
////////// AUTO RUN THE TESTS //////////
var promiseArray = [];
angular.forEach($scope.data.results,function(value,index){
promiseArray.push($scope.runTest(value));
});
$q.all(promiseArray).then(function(){
console.log("Angular is fun !!");
});
});
// test function
$scope.runTest = function(result){
return { then: function(Resolve,Reject){
// if the sessionKey has been set put it in the params
if(result.params.sSessionKey) { result.params.sSessionKey = $scope.sessionKey; console.log($scope.sessionKey); }
// test the method
$http.jsonrpc($scope.data.endPoint, result.method, result.params)
.success(function(data, status, headers, config) {
// if there are no errors
if (data.error === null && !data.result.status) {
// if it's the first test store the sessionKey
if(result.method=='get_session_key') {
$scope.sessionKey = data.result;
if ($scope.sessionKey == data.result) { Resolve(); }
} else {
Resolve();
}
$scope.testSuccess(result, data, status, headers, config);
} else {
Reject();
$scope.testFailed(result, data, status, headers, config);
}
})
.error(function(data, status, headers, config){
Reject();
$scope.testFailed(result, data, status, headers, config);
});
}}
}
$scope.testSuccess = function(result, data, status, headers, config) {
...
}
$scope.testFailed = function(result, data, status, headers, config) {
...
}
});
编辑 2
还有这个:(
////////// AUTO RUN THE TESTS //////////
angular.forEach($scope.data.results,function(value,index){
$scope.runTest(value).then(function(data) {
if(result.method=='get_session_key') {
// if it's the first test store the sessionKey
$scope.sessionKey = data.result;
}
});
});
...
// test function
$scope.runTest = function(result){
var deferred = $q.defer();
// if the sessionKey has been set put it in the params
if(result.params.sSessionKey) { result.params.sSessionKey = $scope.sessionKey; console.log($scope.sessionKey); }
// test the method
$http.jsonrpc($scope.data.endPoint, result.method, result.params)
.success(function(data, status, headers, config) {
// if there are no errors
if (data.error === null && !data.result.status) {
$scope.testSuccess(result, data, status, headers, config);
deferred.resolve(data);
} else {
$scope.testFailed(result, data, status, headers, config);
deferred.reject(data);
}
})
.error(function(data, status, headers, config){
$scope.testFailed(result, data, status, headers, config);
deferred.reject(data);
});
return deferred.promise;
}
这并不像你做的那么难。
根据您的意见进行编辑:
$http.get("functions_as_JSON.php")
.success(function(response) {
$scope.data = response;
$scope.sessionKey = data.result;
var promiseArray = [];
angular.forEach($scope.data.results,function(value,index){
promiseArray.push($scope.runTestPromise(value));
});
$q.all(promises).then(function(){
alert("Angular is fun !!");
});
});
$scope.runTestPromise = function(data){
return { then: function(Resolve,Reject){
if (data == "valid data"){
Resolve("valid data");
} else {
Reject("invalid data");
}
}
我没有 运行 代码,但这是练习,您将测试包装在一个 promise 中,然后让 $q 一个接一个地解决它们。
对了我终于明白了运行:
// populates the table on startup
$http.get("functions_as_JSON.php")
.success(function(response) {
// store the data locally for angular to loop through
$scope.data = response;
////////// AUTO RUN THE TESTS //////////
var currentFunctionIndex = 0;
function nextTest() {
if (currentFunctionIndex < $scope.data.results.length) {
$scope.runTest($scope.data.results[currentFunctionIndex++]).then(nextTest);
}
}
nextTest();
});
...
// test function
$scope.runTest = function(result){
var deferred = $q.defer();
// if the sessionKey has been set put it in the params
if(result.params.sSessionKey) { result.params.sSessionKey = $scope.sessionKey; }
// test the method
$http.jsonrpc($scope.data.endPoint, result.method, result.params)
.success(function(data, status, headers, config) {
// if there are no errors
if (data.error === null && !data.result.status) {
// if it's the first test store the sessionKey
if(result.method=='get_session_key') {
$scope.sessionKey = data.result;
}
$scope.testSuccess(result, data, status, headers, config);
deferred.resolve();
} else {
$scope.testFailed(result, data, status, headers, config);
deferred.reject();
}
})
.error(function(data, status, headers, config){
$scope.testFailed(result, data, status, headers, config);
deferred.reject();
});
return deferred.promise;
}
我有点理解为什么这行得通,但在我看来,文档中可以做更多的工作来解释这一点(尤其是在循环数据时)
我已经写了下面的代码,但是在下一个 ajax 调用 result.params.sSessionKey = $scope.sessionKey
之前分配 $scope.sessionKey = data.result;
时遇到问题(是的 result.name=='get_session_key'
评估循环的第一次迭代)。如您所见,我已经尝试使用 $q
,但是所有关于 promises 和 defer 的教程对我来说都没有任何意义(甚至像 this 这样的东西对我没有帮助)。
你能告诉我如何循环 angular.forEach(...
并仅在前一个测试完成后才执行下一个测试吗?
// Angular's implementation of JSON-RPC (as seen here > http://jsfiddle.net/89D4b/1/)
angular.module("JSON-RPC",[]).config([...]);
// Angular
var app = angular.module('testsApp', ['JSON-RPC']);
app.controller('testsCtrl', function($scope, $http, $q) {
// populates the table on startup
$http.get("functions_as_JSON.php")
.success(function(response) {
// store the data locally for angular to loop through
$scope.data = response;
// create a promise for the sessionKey
var defer = $q.defer();
var promise = defer.promise;
promise.then(function(data){
$scope.sessionKey = data.result;
});
////////// AUTO RUN THE TESTS //////////
angular.forEach($scope.data.results,function(value,index){
$scope.runTest(value);
});
});
// test function
$scope.runTest = function(result) {
// (on all but the first test ...)
// if the sessionKey is in the JSON put it in the params to send with the JSON-RPC
if(result.params.sSessionKey) { result.params.sSessionKey = $scope.sessionKey; }
// test the method
$http.jsonrpc($scope.data.endPoint, result.method, result.params)
.success(function(data, status, headers, config) {
// if there are no errors
if (data.error === null && !data.result.status) {
// on the first test the sessionKey gets stored
if(result.name=='get_session_key') {
$scope.sessionKey = data.result;
//defer.resolve(data);
//$scope.$evalAsync(function($scope) { $scope.sessionKey = data.result; });
}
$scope.testSuccess(result, data, status, headers, config);
} else {
$scope.testFailed(result, data, status, headers, config);
}
})
.error(function(data, status, headers, config){ $scope.testFailed(result, data, status, headers, config); });
}
$scope.testSuccess = function(result, data, status, headers, config) {
result.response = {'status':status, 'post':result.params, 'data':JSON.stringify(data)};
result.status_class = 'positive';
result.status = 'success';
}
$scope.testFailed = function(result, data, status, headers, config) {
result.response = {'status':status, 'post':result.params, 'data':JSON.stringify(data)};
result.status_class = 'negative';
result.status = 'failed';
}
});
编辑
我已经修改成如下,还是不行
// Angular's implementation of JSON-RPC (as seen here > http://jsfiddle.net/89D4b/1/)
angular.module("JSON-RPC",[]).config([...]);
// Angular
var app = angular.module('testsApp', ['JSON-RPC']);
app.controller('testsCtrl', function($scope, $http, $q, $timeout) {
// populates the table on startup
$http.get("limesurvey_api_functions_as_JSON.php")
.success(function(response) {
// store the data locally for angular to loop through
$scope.data = response;
////////// AUTO RUN THE TESTS //////////
var promiseArray = [];
angular.forEach($scope.data.results,function(value,index){
promiseArray.push($scope.runTest(value));
});
$q.all(promiseArray).then(function(){
console.log("Angular is fun !!");
});
});
// test function
$scope.runTest = function(result){
return { then: function(Resolve,Reject){
// if the sessionKey has been set put it in the params
if(result.params.sSessionKey) { result.params.sSessionKey = $scope.sessionKey; console.log($scope.sessionKey); }
// test the method
$http.jsonrpc($scope.data.endPoint, result.method, result.params)
.success(function(data, status, headers, config) {
// if there are no errors
if (data.error === null && !data.result.status) {
// if it's the first test store the sessionKey
if(result.method=='get_session_key') {
$scope.sessionKey = data.result;
if ($scope.sessionKey == data.result) { Resolve(); }
} else {
Resolve();
}
$scope.testSuccess(result, data, status, headers, config);
} else {
Reject();
$scope.testFailed(result, data, status, headers, config);
}
})
.error(function(data, status, headers, config){
Reject();
$scope.testFailed(result, data, status, headers, config);
});
}}
}
$scope.testSuccess = function(result, data, status, headers, config) {
...
}
$scope.testFailed = function(result, data, status, headers, config) {
...
}
});
编辑 2
还有这个:(
////////// AUTO RUN THE TESTS //////////
angular.forEach($scope.data.results,function(value,index){
$scope.runTest(value).then(function(data) {
if(result.method=='get_session_key') {
// if it's the first test store the sessionKey
$scope.sessionKey = data.result;
}
});
});
...
// test function
$scope.runTest = function(result){
var deferred = $q.defer();
// if the sessionKey has been set put it in the params
if(result.params.sSessionKey) { result.params.sSessionKey = $scope.sessionKey; console.log($scope.sessionKey); }
// test the method
$http.jsonrpc($scope.data.endPoint, result.method, result.params)
.success(function(data, status, headers, config) {
// if there are no errors
if (data.error === null && !data.result.status) {
$scope.testSuccess(result, data, status, headers, config);
deferred.resolve(data);
} else {
$scope.testFailed(result, data, status, headers, config);
deferred.reject(data);
}
})
.error(function(data, status, headers, config){
$scope.testFailed(result, data, status, headers, config);
deferred.reject(data);
});
return deferred.promise;
}
这并不像你做的那么难。
根据您的意见进行编辑:
$http.get("functions_as_JSON.php")
.success(function(response) {
$scope.data = response;
$scope.sessionKey = data.result;
var promiseArray = [];
angular.forEach($scope.data.results,function(value,index){
promiseArray.push($scope.runTestPromise(value));
});
$q.all(promises).then(function(){
alert("Angular is fun !!");
});
});
$scope.runTestPromise = function(data){
return { then: function(Resolve,Reject){
if (data == "valid data"){
Resolve("valid data");
} else {
Reject("invalid data");
}
}
我没有 运行 代码,但这是练习,您将测试包装在一个 promise 中,然后让 $q 一个接一个地解决它们。
对了我终于明白了运行:
// populates the table on startup
$http.get("functions_as_JSON.php")
.success(function(response) {
// store the data locally for angular to loop through
$scope.data = response;
////////// AUTO RUN THE TESTS //////////
var currentFunctionIndex = 0;
function nextTest() {
if (currentFunctionIndex < $scope.data.results.length) {
$scope.runTest($scope.data.results[currentFunctionIndex++]).then(nextTest);
}
}
nextTest();
});
...
// test function
$scope.runTest = function(result){
var deferred = $q.defer();
// if the sessionKey has been set put it in the params
if(result.params.sSessionKey) { result.params.sSessionKey = $scope.sessionKey; }
// test the method
$http.jsonrpc($scope.data.endPoint, result.method, result.params)
.success(function(data, status, headers, config) {
// if there are no errors
if (data.error === null && !data.result.status) {
// if it's the first test store the sessionKey
if(result.method=='get_session_key') {
$scope.sessionKey = data.result;
}
$scope.testSuccess(result, data, status, headers, config);
deferred.resolve();
} else {
$scope.testFailed(result, data, status, headers, config);
deferred.reject();
}
})
.error(function(data, status, headers, config){
$scope.testFailed(result, data, status, headers, config);
deferred.reject();
});
return deferred.promise;
}
我有点理解为什么这行得通,但在我看来,文档中可以做更多的工作来解释这一点(尤其是在循环数据时)