2014-02-14 11 views
0

$ q.all을 구현하여 일부 기능을 실행하고 모든 출력을 .then 끝에 첨부 된 함수로 반환하려고합니다.

약속이 올바른 순서로 호출되고 $ all. 결국 끝나고있는 것처럼 보이지만 결과 변수는 널 (null)의 배열로 돌아옵니다 (각 약속에 대해 $ q.all)

JS 바이올린 http://jsfiddle.net/QqKuk/120/에서 발견 될 수 있으며, I는 아래의 난이 코드의 간략화 된 예이다 각도 1.0.1

를 사용하고 있습니다.

여기 내 HTML입니다. 단지 디버그 텍스트와 출력을 표시하기위한 것입니다. 여기

<div ng-controller="MyCtrl"> 
    <p>{{fromThen}}</p> 
    <p>{{fromThen2}}</p> 
    <p>{{runOrder}}</p> 
</div> 

현실 로곤, logTwo에, 내 컨트롤러, 그리고 logThree 동일한 기능 될 수 없습니다.

var myApp = angular.module ('myApp', []);

함수 MyCtrl ($ 범위, $ q를 $ 시간 초과) {

var logOne = function (value) { 
    $scope.fromThen = $scope.fromThen + value; 
    var deffered = $q.defer(); 
    deffered.promise.then(function() { 
      $scope.runOrder = $scope.runOrder + '.logOne()'; 
      $scope.fromThen = $scope.fromThen + value.toUpperCase(); 
      deffered.resolve(value); 
      return deffered.promise; 
    }); 

    deffered.resolve(); 
}; 

var logTwo = function (value) { 
    $scope.fromThen = $scope.fromThen + value; 
    var deffered = $q.defer(); 
    deffered.promise.then(function() { 
      $scope.runOrder = $scope.runOrder + '.logTwo()'; 
      $scope.fromThen = $scope.fromThen + value.toUpperCase(); 
      deffered.resolve(value); 
      return deffered.promise; 
    }); 

    deffered.resolve(); 
}; 

var logThree = function (value) { 
    $scope.fromThen = $scope.fromThen + value; 
    var deffered = $q.defer(); 
    deffered.promise.then(function() { 
      $scope.runOrder = $scope.runOrder + '.logThree()'; 
      $scope.fromThen = $scope.fromThen + value.toUpperCase(); 
      deffered.resolve(value); 
      return deffered.promise; 
    }); 

    deffered.resolve(); 
}; 


$scope.fromThen = ''; 
$scope.fromThen2 = 'No Value'; 
$scope.runOrder = ''; 


$q.all([logOne('One'), logTwo('Two'), logThree('Three')]) 
        .then(function(results) { 
         $scope.runOrder = $scope.runOrder + '.then'; 
         $scope.fromThen2 = results; 
        }); 

} 

내가 갖는 출력은

OneTwoThreeONETWOTHREE 이다, 널, 널 널] .logOne(). logTwo(). logThree(). then

어떤 것들이 올바른 순서로 호출되는 것처럼 보이므로 반환 값에서 null을 얻는 이유가 무엇인지 혼란 스럽습니다. defer.resolve (value)를 잘못 사용하고 있습니까?

여기에 다른 예제를 살펴 봤지만 결과가 나오지 않는 이유를 해결하지 못했습니다.

도움을 주셔서 감사합니다. 이것도 내 첫 번째 게시물이기 때문에, 내가 포함해야하는 정보 (또는 포함 할 필요가없는 정보)에 대한 조언도 감사 할 것입니다.

감사합니다. Neil

답변

2

귀하의 문제는 $q.all에 대한 로그 기능 자체로부터 귀하의 약속을 반환하지 않는다는 것입니다. 당신은 약속을 해결하고 어딘가에 돌려 주지만, 듣는 곳은 아닙니다. .then에 대한 호출 내부 함수는 $q에 의해 호출되며 반환 값은 .then 자체에 대한 약속 확인 콜백으로 보내집니다.이 특정 작업은 정말 필요성도

function doSomethingDeferredWith(data) { 
    var deferredMore = $q.defer(); 
    $scope.fromThen += data; 
    deferredMore.resolve($scope.fromThen); 

: 당신을 doSomethingDeferredWith(data) 때,

var function = doSomthingDeferred(data) { 
    var deferred = $q.defer(); 
    doSomethingDeferredWith(data).then(function(deferredResult) { 
    var processedResult = processDeferredResult(deferredResult); 
    deferred.resolve(processedResult); 
    }); 
    return deferred.promise; 
} 

또는 귀하의 경우에는

var function = doSomthingDeferred(data) { 
    return doSomethingDeferredWith(data).then(function(deferredResult) { 
    var processedResult = processDeferredResult(deferredResult); 
    return processedResult; 
    }); 
} 

: 귀하의 유망 기능은 형태를 취한다을 연기하면 즉시 완료되지만를 쿼리하는 경우기반 서비스, 당신은 다시 deferredMore 약속을 얻을 것 :

return deferredMore.promise; 
} 

를 그런 다음, 당신은에 대한 호출에서 참조하는 함수에 매개 변수로 어떤 결과를 얻을 거라고 수행을 완료 한 후 것과 같은 promise.thendoSomethingDeferredWith에서 반환

doSomethingDeferredWith(data).then(function(deferredResult) { 

지금 방식 때문에 $q 작품으로, doSomethingDeferredWith(data)에 대한 호출이 약속 반환 .then는 그 약속 최대 대기 전달 된 함수를 호출, 현재 스크립트 루프가 끝날 때까지 실행되지 않습니다. 즉, .then이 호출되고 해당 함수가 대기열에 들어간 다음 doSomethingDeferred이 실행을 계속 수행하고 해당 호출 함수가 호출 스택이 지워질 때까지 실행을 계속합니다. 그 후에야 만 $q이 해결 된 약속을 위해 모든 콜백을 수행 할 기회를 갖게됩니다.

코드에서 doSomethingDeferred, 다양한 log*** 함수는 실제로 약속을 반환하지 않습니다. 그들은 undefined을 반환합니다. doSomethingDeferred 대신에 $q이 콜백을 실행하면 생성 된 약속을 반환하면 $q.all의 콜백에 데이터를 가져올 수 있습니다.

그들은 $q이 따를 수 있음을 약속하고 실행있을거야, 그런 다음, 로그 함수의 반환 값은 undefined을하지 않습니다 return deffered.promise;에 로그 파일의 각각의 끝에서 deffered.resolve(); 통화를 변경, 코드를 수정하려면 세 번의 호출이 모두 끝난 후 즉시 .resolve 세 가지 호출에 대한 콜백을 수행하고 각각의 개별 약속이 지연 기능의 클로저 프레임에서 value으로 해결 될 때 의 배열로 $scope.runFrom2 값을 설정합니다.

TL; DR 버전

변경 로그 파일의 각 끝 부분에있는 deffered.resolve(); 호출 내가 사용에 대한 팁에 대한 감사가 필요 정확히이었다 return deffered.promise;

+1

에 doSomethingDeferredWith()에서 추가 연기가 발생했습니다. –

+0

네, 종종'$ http'처럼 지연된/약속하는 패턴을 사용합니다. '$ http'가 근본적으로하고있는 것은 새로운 지연 객체를 생성하고 그것을 기본'XmlHttpRequest'를위한'onreadystatechange' 핸들러에서 해결하는 것입니다. '그 기억하는 것도 중요합니다.then'은 매개 변수로서 전달 된 함수가 반환 될 때 해결되는 약속 그 자체를 리턴합니다. 그래서'$ q.all' 호출로도 약속을 연결시킬 수 있습니다. – citizenslave

관련 문제