使用$ q.all控制Angularjs微调器

时间:2021-06-07 00:19:45

I am implementing a spinner functionality in my project. The gold is to show the spinner when one or multiple http requests are fired, and hide the spinner when the requests are successful. Because I don't know which request will be resolved first, I chose to use $q.all. I have a directive like this:

我正在我的项目中实现微调器功能。黄金是在触发一个或多个http请求时显示微调器,并在请求成功时隐藏微调器。因为我不知道哪个请求会先解决,所以我选择使用$ q.all。我有一个这样的指令:

angular.module('myApp', [])
  .directive('spinner', function($q, $http) {
    return {
      controller: function($scope) {
        $scope.showSpinner = true;
        var self = this;
        self.promises = [];

        self.makeHeader = function() {
          self.promises.push($http.get('some/url'));
          // Code that builds header goes here.
        };

        self.makeFooter = function() {
          self.promises.push($http.get('other/url'));
          // Code that builds footer goes here.
        };

        self.makeHeader();
        self.makeFooter();

        // Initial page load
        $q.all(self.promises).then(function() {
          // Hide the spinner.
          $scope.showSpinner = false;
        });
      }   
    }
  });

The initial load works fine, but when user has an interaction which requires multiple calls to server, to rebuild the header and footer. How do I show the spinner again and hide it when the promises are resolved?

初始加载工作正常,但是当用户进行需要多次调用服务器的交互时,重建页眉和页脚。如何在承诺解决后再次显示微调器并隐藏它?

1 个解决方案

#1


1  

You can wrap the repeated calls into a function. I also recommend to make the 2 functions to return promise instead of handling the $http promise inside to provide more flexibility.

您可以将重复的调用包装到函数中。我还建议让2个函数返回promise而不是处理$ http promise里面以提供更多的灵活性。

angular.module('myApp', [])
  .directive('spinner', function($q, $http) {
    return {
      controller: function($scope) {
        var self = this;

        self.makeHeader = function() {
          return $http.get('some/url').then(function() {
            // Code that builds header goes here.
          });          
        };

        self.makeFooter = function() {
          return $http.get('other/url').then(function() {
            // Code that builds footer goes here.
          }); 
        };

        self.build = function() {
          $scope.showSpinner = true;
          self.promises = [];

          self.promises.push(self.makeHeader());
          self.promises.push(self.makeFooter());

          $q.all(self.promises).then(function() {
            // Hide the spinner.
            $scope.showSpinner = false;
          });
        }

        // initial run
        self.build();

        // subsequent call
        self.someClickHandler = function() {
          self.build();
        }

        // some other calls that need to use spinner
        self.other = function() {
          $scope.showSpinner = true;
          self.promises = [];

          self.promises.push(self.otherCall());

          $q.all(self.promises).then(function() {
            // Hide the spinner.
            $scope.showSpinner = false;
          });
        }
      }   
    }
  });

As you can see this approach would look better if you always call same set of functions every time, but what if you need to use spinner on other cases like self.other?

正如你所看到的那样,如果你每次都调用相同的函数集,这种方法看起来会更好,但是如果你需要在self.other等其他情况下使用微调器呢?

You can wrap the spinner in a function and pass it the promise array.

您可以将微调器包装在函数中并将其传递给promise数组。

var showSpinner = function(promises) {
  $scope.showSpinner = true;

  $q.all(promises).then(function() {
    // Hide the spinner.
    $scope.showSpinner = false;
  });
}

self.build = function() {
  var promises = [];

  promises.push(self.makeHeader());
  promises.push(self.makeFooter());

  showSpinner(promises);
}

self.other = function() {
  var promises = [];       
  promises.push(self.otherCall());

  showSpinner(promises);
}

Looks cleaner?

#1


1  

You can wrap the repeated calls into a function. I also recommend to make the 2 functions to return promise instead of handling the $http promise inside to provide more flexibility.

您可以将重复的调用包装到函数中。我还建议让2个函数返回promise而不是处理$ http promise里面以提供更多的灵活性。

angular.module('myApp', [])
  .directive('spinner', function($q, $http) {
    return {
      controller: function($scope) {
        var self = this;

        self.makeHeader = function() {
          return $http.get('some/url').then(function() {
            // Code that builds header goes here.
          });          
        };

        self.makeFooter = function() {
          return $http.get('other/url').then(function() {
            // Code that builds footer goes here.
          }); 
        };

        self.build = function() {
          $scope.showSpinner = true;
          self.promises = [];

          self.promises.push(self.makeHeader());
          self.promises.push(self.makeFooter());

          $q.all(self.promises).then(function() {
            // Hide the spinner.
            $scope.showSpinner = false;
          });
        }

        // initial run
        self.build();

        // subsequent call
        self.someClickHandler = function() {
          self.build();
        }

        // some other calls that need to use spinner
        self.other = function() {
          $scope.showSpinner = true;
          self.promises = [];

          self.promises.push(self.otherCall());

          $q.all(self.promises).then(function() {
            // Hide the spinner.
            $scope.showSpinner = false;
          });
        }
      }   
    }
  });

As you can see this approach would look better if you always call same set of functions every time, but what if you need to use spinner on other cases like self.other?

正如你所看到的那样,如果你每次都调用相同的函数集,这种方法看起来会更好,但是如果你需要在self.other等其他情况下使用微调器呢?

You can wrap the spinner in a function and pass it the promise array.

您可以将微调器包装在函数中并将其传递给promise数组。

var showSpinner = function(promises) {
  $scope.showSpinner = true;

  $q.all(promises).then(function() {
    // Hide the spinner.
    $scope.showSpinner = false;
  });
}

self.build = function() {
  var promises = [];

  promises.push(self.makeHeader());
  promises.push(self.makeFooter());

  showSpinner(promises);
}

self.other = function() {
  var promises = [];       
  promises.push(self.otherCall());

  showSpinner(promises);
}

Looks cleaner?