11

我无法理解 AngularJS 的承诺概念。

我有一个提供者:

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

packingProvider.provider('packingProvider',function(){
    return{
       $get: function($http){
           return{
              getPackings: function(){
                  $http.post('../sys/core/fetchPacking.php').then(function(promise){
                      var packings = promise.data;
                      return packings;
                  });
              }
           }
       }
   }
});

如您所见,这提供了一个方法getPackings(),它将返回一个对象

现在,如果我在主应用程序中使用它来接收数据,则调用将是异步的,从而导致我不得不“等待”数据的问题:

var packings = packingProvider.getPackings();

console.log(packings); // undefined

如果不将流程重构到我的主控制器中,我将如何做到这一点?

4

3 回答 3

7

尝试

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

packingProvider.provider('packingProvider',function(){
    return{
       $get: function($http){
           return{
              getPackings: function(){
                  return $http.post('../sys/core/fetchPacking.php').then(function(response){
                      return response.data; // packings
                  });
              }
           }
       }
   }
});

然后

packingProvider.getPackings().then(function(packings){
    console.log(packings);
});

主要思想:您需要从 getPackings 函数返回承诺对象。不确定您是否可以同步调用它,但这样做几乎绝对不是一个好主意。此外,如果您想在控制器上“打包”模型对象并用于双向绑定,您可以安全地分配 promise 对象,Angular 将在数据通过时立即解析:

$scope.packings = packingProvider.getPackings();

更新

从 1.2.0-rc.3 开始,承诺展开已被弃用(https://github.com/angular/angular.js/blob/master/CHANGELOG.md#120-rc3-ferocious-twitch-2013-10-14 ) ,因此上面的代码行将不再导致双向绑定。

于 2013-10-08T14:16:29.090 回答
7

then当您认为返回时,您的方法中的返回值没有返回;它稍后会返回。

在语句var packings = packingProvider.getPackings();中,返回值是未定义的,因为返回的承诺$http是异步的。这意味着调用$http.post发生,没有完成,然后你的函数返回。在不返回任何内容的 JS 函数中返回未定义。该post调用稍后完成并执行,该调用return packings;无处返回。

getPackings方法可能应该$http.post直接返回承诺。这样,任何想要使用此方法的代码都可以then直接调用 Promise 并按照需要的方式设置值。在控制器中,您可以将该承诺直接分配给 the$scope并在您的视图中使用它。这是一篇很好的文章,解释了该特定功能: http: //markdalgleish.com/2013/06/using-promises-in-angularjs-views/

顺便说一句,看起来您在那里有一个冗长的服务声明;有什么理由不把它缩短成这样吗?

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

module.service('packing', function($http) {
  return {
    getPackings: function() {
      return $http.post('../sys/core/fetchPacking.php');
    }
  };
});

我对 AngularJS 比较陌生,但我没有看到所有打字有任何收获。( =

于 2013-10-08T14:20:03.527 回答
1

有大量可用资源向您展示如何将 Deferreds/Promises 与 jQuery 一起使用。尝试搜索那些,这可能会帮助你克服这个障碍。Afaik,AngularJS 承诺与 jQuery 承诺相同。

使用 jQuery 承诺是这样的:

var getPackings = function() { return $.get('../sys/core/fetchPacking.php'); };
var packings;
$.when(getPackings()).then(function(data){ packings = data; console.log(packings) });

请记住,尽管 jQuery ajax 调用具有 .done、.success 等函数,但它们将取代通用 Deferreds 的 .when().then() 函数。

在上面的 jQuery 方法中,您可以看到我们必须在 .then() 函数中设置数据并将其输出,因为您无法保证异步过程在其他任何地方完成。因此,理想情况下,您可以调用任何函数继续在 .then() 函数中进行处理,如下所示:

$.when(myAsyncFunc()).then(myAppCanContinue(dataReturnedByAsyncFunc));

Angular 将遵循相同的逻辑。如果您了解上述内容,应该更容易理解如何在 Angular 中完成此操作。另外,请查看这篇给出简单示例的文章:http: //markdalgleish.com/2013/06/using-promises-in-angularjs-views/

为了让您的代码正常工作,您需要执行以下操作:

packingProvider.provider('packingProvider',function(){
    return{
       $get: function($http){
           return{
              getPackings: function(){
                  return $http.post('../sys/core/fetchPacking.php');
              }
           }
       }
   }
});
var packings = packingProvider.getPackings();

packings.then(function(data) { console.log(data)});
于 2013-10-08T14:45:39.537 回答