2014-02-14 4 views
0

Я пытаюсь реализовать $ q.all для запуска некоторых функций, а затем возвращать все выходы в функцию, прикрепленную к. Then в конце.

В настоящее время обещания выглядят так, как будто они звонят в правильном порядке, а $ all. Then происходит в конце, но переменная результатов возвращается с массивом нулей (по одному для каждого обещания в $ q.all)

JS Фидл можно найти на http://jsfiddle.net/QqKuk/120/ и я использую угловой 1.0.1

ниже приведен упрощенный пример кода я.

Вот мой html, просто там, чтобы отобразить отладочный текст и вывод.

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

и вот мой контроллер, в действительности Logone, logTwo и logThree не будет одинаковых функций.

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

функция MyCtrl ($ Объем, $ д, $ таймаут) {

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 [NULL, NULL, NULL] .logOne(). logTwo(). logThree(). then

Которая для меня выглядит так, как будто вещи звонят в правильном порядке, поэтому я смущен, почему я получаю нули в возвращаемом значении. Я использую defer.resolve (значение) неправильно?

Я рассмотрел некоторые другие примеры здесь, но я не смог понять, почему я не получаю результата.

Спасибо за любую помощь, которую вы можете дать. Поскольку это также мой первый пост, все советы о том, какую информацию я должен включать (или не нужно включать), также будут оценены.

Спасибо. Neil

ответ

2

Ваша проблема в том, что вы не возвращаете свои обещания из самих функций журнала для $q.all. Вы решаете обещания и возвращаете их где-то, но не в любое место, где вы слушаете. Функции внутри вызовов до .then вызывают $q, а возвращаемые значения отправляются на обратные вызовы разрешения для обещаний. .then сам возвращается.Ваши перспективные функции должны иметь вид:

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

В вашем случае, когда вы doSomethingDeferredWith(data) вас:

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

Это конкретное действие не действительно необходимости быть отложенным, он заканчивается немедленно, но если вы запрашивали $http сервиса на основе, то вы получите ваше deferredMore обещание назад:

return deferredMore.promise; 
} 

Затем, после того, как вы закончите делать это, вы собираетесь получить какой-то результат в качестве параметра функции, указанной в вызове .then на promise как тот вернулся из doSomethingDeferredWith:

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

Теперь, из-за способом $q работ, вызов doSomethingDeferredWith(data) возвращает обещание, .then называется это обещание и функции Передаваемых в очереди, , но не выполняется до окончания текущего цикла цикла. Это означает, что вызывается .then, функция ставится в очередь, а затем doSomethingDeferred продолжает выполнение, возвращает, а его вызывающая функция продолжает выполнение до тех пор, пока стек вызовов не будет очищен. Только после этого $q имеют возможность вернуться и запустить все обратные вызовы для разрешенных обещаний.

В вашем коде doSomethingDeferred, различные функции log***, на самом деле не верьте обещание. Они возвращаются undefined. Если вместо этого вы вернете обещание, которое мы создали, и оно разрешится, когда $q запустит обратный вызов, а не в конце doSomethingDeferred, вы получите свои данные в обратном вызове для $q.all.

Чтобы исправить код, измените deffered.resolve(); вызовы в конце каждого из файлов журналов в return deffered.promise; Затем возвращаемые значения для функций журнала не будет undefined, они будут обещания, которые $q могут следовать и бежать обратный вызов по всем трем их .resolve вызывает сразу после всех трех вызовов, устанавливая значение $scope.runFrom2 в массив из ['One','Two','Three'], поскольку каждое индивидуальное обещание разрешается с помощью value из кадра закрытия функции отсрочки.

Т.Л., др Версия

Измените deffered.resolve(); вызовы в конце каждого из файлов журнала return deffered.promise;

+1

Это было именно то, что мне нужно, спасибо за подсказку об использовании добавьте defer в doSomethingDeferredWith(), поскольку это было что-то еще, к чему я буду двигаться дальше. –

+0

Да, часто вы будете использовать шаблон отложенного/обещания с услугами, которые откладываются, например '$ http'. Фактически «$ http» создает новый отложенный объект и разрешает его в обработчике 'onreadystatechange' для базового' XmlHttpRequest'. Также важно помнить, что '.то «возвращает само обещание, которое разрешается, когда функция, переданная в качестве параметра, возвращается, что позволяет вам связывать обещания даже с вызовом' $ q.all'. – citizenslave

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