【问题标题】:Controller Making Multiple Synchronous Nested Service Calls控制器进行多个同步嵌套服务调用
【发布时间】:2017-10-03 07:03:41
【问题描述】:

在下面的简单示例中,我有一个方法调用 (getMoreProducts) 需要在第一个方法调用 (getProducts) 完成后调用。

由于我是 angularjs 的新手(对 JS 也很陌生),我想确认是否有其他方法可以实现这一点。我担心的是,如果需要在getMoreProducts 之后调用另一个方法,那么代码将是三层深度,以此类推。

.controller('ProductController',function(ProductService, $scope){
  $scope.products = [];
  $scope.moreProducts  = [];

  ProductService.getProducts().then(function(res){
     $scope.products = res.data;

     ProductService.getMoreProducts().then(function(res){
        $scope.moreProducts = res.data;
     });
  });

对于此示例,假设 ProductService 方法只是调用 HTTP GET 调用。

【问题讨论】:

标签: javascript angularjs


【解决方案1】:

在 OP 的嵌套 promise 中使用的反模式是一种“回调地狱”形式,这正是 promise 应该帮助解决的问题。

当下一个调用依赖于上一个调用时,promise 应该串联起来,这样它们的深度不会超过 1 级:

  ProductService.getProducts().then(function (productsRes) {
     $scope.products = productsRes.data;
     return ProductService.getMoreProducts();
  })
  .then(function (moreProductsRes) {
      $scope.moreProducts = moreProductsRes.data;
     return ProductService.getEvenMoreProducts();
  })
  .then(function (evenMoreProductsRes) { ... });

当 Promise 不依赖于彼此的结果时(如本例),它们可以并行执行,这就是 $q.all 的用途:

$q.all([ProductService.getProducts(), ProductService.getMoreProducts()])
.then(function (responses) {
   var productsRes = responses[0];
   var moreProductsRes = responses[1];
   $scope.products = productsRes.data;
   $scope.moreProducts = moreProductsRes.data;
});

【讨论】:

    【解决方案2】:

    是的,您可以利用承诺链。如果你在另一个中返回一个承诺,你可以避免讨厌的嵌套:

    var app = angular.module('plunker', []);
    
    
    // Before
    app.controller('MainCtrl', function($scope, ProductService) {
      $scope.name = 'World';
    
      $scope.products = [];
      $scope.moreProducts  = [];
    
      ProductService.getProducts().then(function(res){
        $scope.products = res.data;
    
        ProductService.getMoreProducts().then(function(res){
            $scope.moreProducts = res.data;
        });
      });
    });
    
    // After with promise chaining
    app.controller('MainCtrl', function($scope, ProductService) {
      $scope.name = 'World';
    
      $scope.products = [];
      $scope.moreProducts  = [];
    
      ProductService.getProducts().then(function(res){
        $scope.products = res.data;
        return ProductService.getMoreProducts()
      })
      .then(function(res){
          $scope.moreProducts = res.data;
      });
    });
    
    
    app.service('ProductService', function($timeout){
      this.getProducts = function() {
        return $timeout(function(){
          return {
            data: [{name: 'Widget', color: 'blue'}]
          }
        }, 500)
      }
    
      this.getMoreProducts = function() {
        return $timeout(function(){
          return {
            data: [{name: 'Widget', color: 'green'}, {name: 'Widget', color: 'red'}]
          }
        }, 1000)
      }
    })
    

    根据getProductsgetMoreProducts 调用的要求,您可以使用参数而不是创建不同的函数。

    http://plnkr.co/edit/K4LPKWSD06QnwbRk8k0B?p=preview

    编辑:

    顺便说一句,我不推荐这种创建控制器和服务的方式,它只是默认的 plunker 模板。

    Y021Y022Y031

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-22
      • 1970-01-01
      • 2013-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-27
      • 1970-01-01
      相关资源
      最近更新 更多