restangular: is it possible to have a progress bar

2019-05-25 03:00发布

问题:

I have this code (in a service) based on restangular (it works):

sendFile: function (params) {
                console.log('sendFile');
                console.log(params);
                return this.restfulBase().post('file.json',params,{},{ 'X-CSRF-Token' : ipCookie('csrftoken')});
            }

How can I, in my controller/directive, get the progress of this upload only with use of Restangular ? I have read that I can write my upload function that use directly XHR or a jQuery plugin like FileUpload, but i want to use only restangular so that my user don't load useless js files.

Or is there a possibility to intercept when upload start ? In this way I can write a div "Loading..." (ok, it is not good like a progress bar, is better than nothing).

Thanks.

回答1:

You can do that using HTTP Interceptors. This will be just few lines of code in your app which works well with Restangular. Using this you can determine when a request started and response is received. Also check how many pending request exist. Below is the sample code that might help. Read more about HTTP Interceptors in Angular.

{

    'request': function(config) {
        rootScope = rootScope || $injector.get('$rootScope');
        rootScope.$broadcast('_START_REQUEST_');
        return config || $q.when(config);
    },

    'requestError': function(rejection) {
        return $q.reject(rejection);
    },

    'response': function(response) {

        if (response.status === 200) {
          // do stuff when success
        }

        $http = $http || $injector.get('$http');

        if ($http.pendingRequests.length < 1) {
            rootScope = rootScope || $injector.get('$rootScope');
            rootScope.$broadcast('_END_REQUEST_');
        }

        return response || $q.when(response);
    },

}

Later in your controller/service you can check if

$rootScope.$on('_END_REQUEST', function() {
    // do stuff on request completed 
});

The above code have syntax errors. But that's how it works. You will get many examples about HTTP Interceptor.

Hope that helps :)



回答2:

As far as I know, there is no way to track the progress of a RESTful request, like you would with a normal file upload.

I've been trying to find the exact same thing for a couple weeks now, but to no avail.

Following what the previous answers mention, the only states you can really track are:

  • Your pre-request (before its upload has started)
  • During request (while its uploading)
  • A completed request (successful/unsuccessful transfer)

And if you'd like, the time it takes for the request to complete. Hope this helps :)



回答3:

Here is my solution to create a Restangular animationd during api requests.

First add a response interceptor and a request interceptor that sends out a rootscope broadcast. Then create a directive to listen for that response and request.:

         angular.module('mean.system')
  .factory('myRestangular',['Restangular','$rootScope', function(Restangular,$rootScope) {
    return Restangular.withConfig(function(RestangularConfigurer) {
      RestangularConfigurer.setBaseUrl('http://localhost:3000/api');
      RestangularConfigurer.addResponseInterceptor(function(data, operation, what, url, response, deferred) {
        var extractedData;
        // .. to look for getList operations
        if (operation === 'getList') {
          // .. and handle the data and meta data
          extractedData = data.data;
          extractedData.meta = data.meta;
        } else {
          extractedData = data.data;
        }
        $rootScope.$broadcast('apiResponse');
        return extractedData;
      });
      RestangularConfigurer.setRequestInterceptor(function (elem, operation) {
        if (operation === 'remove') {
          return null;
        }
        return (elem && angular.isObject(elem.data)) ? elem : {data: elem};
      });
      RestangularConfigurer.setRestangularFields({
        id: '_id'
      });
      RestangularConfigurer.addRequestInterceptor(function(element, operation, what, url) {
        $rootScope.$broadcast('apiRequest');
        return element;
      });
    });
  }]);

Here is the directive:

        angular.module('mean.system')
  .directive('smartLoadingIndicator', function($rootScope) {
    return {
      restrict: 'AE',
      template: '<div ng-show="isAPICalling"><p><i class="fa fa-gear fa-4x fa-spin"></i>&nbsp;Loading</p></div>',
      replace: true,
      link: function(scope, elem, attrs) {
        scope.isAPICalling = false;

        $rootScope.$on('apiRequest', function() {
          scope.isAPICalling = true;
        });
        $rootScope.$on('apiResponse', function() {
          scope.isAPICalling = false;
        });
      }
    };
  })
;