处理ajax请求的流控制(即只在前一个请求完成后处理下一个请求)

Flow control of processing ajax requests (i.e. only processing the next request after the previous request has completed)

本文关键字:请求 一个 下一个 后处理 ajax 流控制 处理      更新时间:2023-09-26

我写了下面的代码,但我有一个问题,在分配$scope.sessionKey = data.result;之前,它被传递到下一个ajax调用result.params.sSessionKey = $scope.sessionKey(是的,result.name=='get_session_key'评估循环的第一次迭代)。正如你所看到的,我已经尝试过使用$q,但是所有关于承诺和延迟的教程对我来说都没有任何意义(甚至像这样的东西也没有帮助我)。

你能告诉我如何在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");
     }
}

我没有运行代码,但这是练习,你把你的测试包在一个承诺,然后你让$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;
}

我有点理解为什么会这样,但在我看来,在文档中可以做更多的事情来解释这一点(特别是当循环通过数据时)