2014-12-18 2 views
0

Я хотел бы использовать $ q.all, чтобы дождаться завершения функции. У меня есть пример в plunker http://plnkr.co/edit/uG2JujPqoiBgqtRjEZwh?p=preview

<html> 
<head> 
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.min.js"></script> 
</head> 
<body ng-app="App"> 
    <div ng-controller="AppController"> 
     Its the app 
     <button ng-click="run()">Run (check console)</button> 
    </div> 

    <script> 
    var App = angular.module("App", []); 
    App.controller("AppController", function($scope,$q){ 

     $scope.xxy = function(num){ 
      var d = $q.defer(); 
      for(var i=0;i<100000;i++){ 
       //do nohing 
      } 
      d.resolve(num*20); 

      var promise = d.promise; 

      return $q.all([promise]).then(function(data){ 
       return data; 
      }); 

     }; 

     $scope.run = function(){ 
      for(var i=0;i<10;i++){ 
       console.log(i); 
       console.log($scope.xxy(i)); 
       //$scope.xxy(i).then(function(r){ 
       // console.log(r); 
       //}) 
      }  
     }; 
    }); 

    </script> 
</body> 
</html> 

Функция XXY() является тот, который написал асинхронной путь, но я хочу быть синхронизации с помощью $ q.all. Не могу изменить характер функции xxy, так как тогда он сломает другие вещи в моем большом проекте. xxy() - это простая версия большой функции, которую я использую, и ее сборку с использованием $ q.defer.

Поэтому в основном я хочу выход быть: 1 20 2 40 ... а не как его в настоящее время 1 2 .. 20 40 ...

+0

plunker or fiddle please – Alp

+0

Это выше кода – zPrima

ответ

1

Итак, вы хотите сериализовать поведение: напечатайте 1, вызовите функцию async и напечатайте возвращаемое значение 20, и только затем запустите цикл снова, напечатайте 2, затем вызовите функцию async и т. Д.?

Действительно интересный вопрос. Мне кажется, что вам нужно использовать repeater pattern.

Применительно к вашему делу:

App.controller("AppController", function($scope,$q,$timeout) { 

    $scope.xxy = function(num) { 
     var d = $q.defer(); 

     $timeout(function() { 
      d.resolve(num*20); 
     }, 1000); 

     return d.promise; 
    }; 

    $scope.repeater = function(i) { 
     if (i < 10) { 
      console.log(i); 
      $scope.xxy(i).then(function(ret) { 
       console.log(ret); 
       $scope.repeater(i + 1); 
      }); 
     } 
    }; 

    $scope.run = function() { 
     $scope.repeater(0); 
    }; 
}); 

Смотрите в действии: JSFiddle.

Я добавил $timeout, чтобы продемонстрировать асинхронное поведение и возможность разрешить обещание обратного вызова там, где он принадлежит.

Надеюсь, я правильно понял вашу проблему.

+0

Я вижу, ретранслятор является, в основном, рекурсивной функцией, заменил $ scope на обычные функции, так что проверка области угловой области не срабатывает. Решает проблему, которая у меня есть. Спасибо. – zPrima

0

$scope.xxy(i) возвращает обещание.

Вы не можете просто петли и ждать возврата. Обещания не работают.

Вместо этого вы должны это сделать.

$scope.xxy(num).then(function(value){ 
     ... 
}); 

$q.all(..) оборачивает все обещания в массиве в новое обещание.

+0

Итак, что я могу сделать, чтобы сделать функцию, которая возвращает обещание подождать, пока это не будет сделано, а затем продолжите нормально. В основном мне нужно каким-то образом обмануть функцию async для синхронизации. – zPrima

1

Проблема заключается в функции запуска .... Вы в настоящее время это закомментирована ....

$scope.xxy(i).then(function(r){ 
    console.log(r); 
}) 

но $ q.all решает массив результатов (в порядке того, как обещания передаются, поэтому вам нужно использовать это ...

$scope.xxy(i).then(function(r){ 
    console.log(r[0]); // first item of the result array 
}) 

EDIT Здесь он работает в обновленном plnkr

Из документации (link) Объединение нескольких обещаний в единое обещание, которое разрешается, когда все обещания ввода разрешены. возвращается: Массив или хэш обещаний.

+0

Выход, который мне нужен, это 1 20 2 40 ... в настоящее время вывод 1 2 .. 20 40. Я хочу использовать функцию xxy как вызов synchonus, но я не могу изменить ядро ​​функции xxy в моем проекте потому что он слишком большой и может сломать некоторые другие вещи. – zPrima