2015-05-21 2 views
1

Я написал следующий код, но у меня возникла проблема с назначением $scope.sessionKey = data.result;, прежде чем он будет передан в следующем вызове ajax result.params.sSessionKey = $scope.sessionKey (и да result.name=='get_session_key' оценивает первую итерацию цикла). Как вы можете видеть, я пробовал пойти с $q, но все учебники по обещаниям и отступам просто не имеют для меня никакого смысла (даже такие вещи, как this, мне не помогают).Управление потоком обработки запросов ajax (т. Е. Обработка только следующего запроса после завершения предыдущего запроса)

Не могли бы вы показать мне, как пройти через 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'; 
    } 
}); 

EDIT

Я изменил его на следующий, но все без толку

// 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) { 
     ... 
    } 
}); 

EDIT 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; 
} 

ответ

0

Право я, наконец, получил это работает с:

// 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; 
} 

Я отчасти понимаю, почему это работает, но на мой взгляд, гораздо больше можно было бы сделать в документации, чтобы объяснить это (особенно если цикл по данным)

1

Это не так сложно, как вы это делаете.

Редактирование на основе ваших комментариев:

$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"); 
    } 
} 

Я не запускать код, но это сеялка, вы заключаете свой тест на обещание, а затем вы позволите $ д разрешить их один за другим.

+0

Я не уверен, что вы говорите. '$ scope.sessionKey = data.result;' должен быть назначен в первом runTest, который будет использоваться во втором runTest. Также '$ scope.runTest = {then: function (onResolve, onReject) {' не является вызовом функции (я думаю). Любой шанс, который вы можете поместить в завершенный пример – Sevenearths

+1

Надеюсь, это легче понять сейчас. Это всего лишь способ объединить обещания в $ q, я не так сильно смотрю на ваш код. –

+0

(BTW '$ scope.sessionKey = data.result' основан на успешном возврате' data.result' в первом цикле 'angleular.forEach (...') – Sevenearths

Смежные вопросы