如何中止或取消Angularjs $资源请求并覆盖本地数据的响应

时间:2016-12-08 02:41:15

标签: angularjs ngresource angular-http-interceptors angularjs-ng-resource

在我的一个新项目中,我使用AngularJS $资源进行http调用。当没有互联网连接时,我需要显示本地数据(来自SQLite)。

我通过以下步骤聚集了我的障碍,并在

下面创建了示例代码
  • 第1步:点击该按钮,调用$ resource // Done
  • 第2步:在发送请求之前,请检查机器是否连接到 网络//完成
  • 第3步:如果网络连接,请获取响应//完成
  • 第4步:如果没有网络,则中止请求//完成
  • 第5步:如果没有网络将本地数据响应给$ resource承诺 - 不确定如何执行此操作。



var servicetest = angular.module('servicetest', ['ngResource'])
.factory('interceptors' ,function($rootScope, offlineCntrl){
  return {
      'request':function(request){
        if(!offlineCntrl.isOnline()){
          //there wont be a server call
          request.url='';
          //Abort the request
          request.timeout;
        }else{
          return request;
        }
      },
   
     'response':function(response){
        if(!offlineCntrl.isOnline()){
           offlineCntrl.assignLocal(request).then(function(data){
            //Get the local data here.
            // Have to pass this data to my response
            // At this stage I am getting an error attached below
            response.data = data;
            return response;
          })
          
        }else{
         return response;
        }
     }
   }
})
.config(function($httpProvider){
  $httpProvider.interceptors.push('interceptors');
})
.factory('offlineCntrl', function($q, $timeout){
  return {
    isOnline: function(){
      return navigator.onLine;
    },
    assignLocal:function(request){
      var defer = $q.defer();
      $timeout(function(){
        defer.resolve({title:"local", body:"Local local data context"});
      })
      return defer.promise;
    }
  }
})
.factory('CloudSerivce', function($resource){
  return $resource('https://jsonplaceholder.typicode.com/posts/:id', {
    id:'@id'
  }, {
     get:{
       method:"GET",
			 isArray:false,
			 cancellable: true
     }
  })
})
.controller('mainCntrl', function($scope, CloudSerivce){
  $scope.data = {};

  $scope.getCloudService = function(){
    CloudSerivce.get({id:1}).$promise.then(function(data){
      //It should receive local data if there is no network
      $scope.data = data;
    }, function(err){
      console.log(err)
    })
  }

})

<html ng-app="servicetest">
  <body ng-controller='mainCntrl'>
    <h1>{{data.title}}</h1>
    <p>{{data.body}}</p>
    <button ng-click='getCloudService()'>
      GET ITEMS
    </button>
    <h4>Try the button disabling your internet connection</h4>
  </body>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular-resource.min.js"></script>
</html>
&#13;
&#13;
&#13;

当我尝试使用延迟承诺事件返回响应时,我收到错误。

 TypeError: Cannot read property 'headers' of undefined
at f (angular.js:7520)
at C (angular.js:10924)
at angular.js:11010
at h.$eval (angular.js:11930)
at h.$digest (angular.js:11756)
at a.$apply (angular.js:12036)
at HTMLButtonElement.<anonymous> (angular.js:17871)
at angular.js:2612
at q (angular.js:309)
at HTMLButtonElement.c (angular.js:2611)

我可以通过冒泡$ rootScope发射器并在控制器中捕获它来做到这一点,但我相信最简单的方法是在中止请求后破解ngResource(CloudService $ promise事件)响应。 这样我就可以保持控制器的getCloudService功能,它可以在离线和在线模式下工作。

3 个答案:

答案 0 :(得分:1)

你在这里搞错了!

$scope.getCloudService = function(){
    CloudSerivce.get({id:1}).$promise.then(function(response){
      //It should receive local data if there is no network
      $scope.data = response.data;//modified
    })
  }

另外要处理错误情况,你应该使用像这样的东西吗?

 $scope.getCloudService = function(){
        CloudSerivce.get({id:1}).$promise.then(function(response){
          //It should receive local data if there is no network
          $scope.data = response.data;//modified
        }),function(error){
             //ERROR HANDLING 
        });
 }

答案 1 :(得分:1)

需要做类似的事情

.factory('interceptors' ,function($rootScope, offlineCntrl){
        return {
          'request':function(request){
            if(!offlineCntrl.isOnline()){
              //there wont be a server call
              request.url='';
              //Abort the request
              request.timeout;
            }else{
              return request;
            }
          },

          'response':function(response){
            const deferred = $q.defer();
            if(!offlineCntrl.isOnline()){
              offlineCntrl.assignLocal(request).then(function(data){
                deferred.resolve(data);
              });

            }else deferred.resolve(response);
            return deferred.promise;
          }
        }
      })

答案 2 :(得分:0)

以下解决方法已经解决了。

var servicetest = angular.module('servicetest', ['ngResource'])
.factory('interceptors' ,function($rootScope, offlineCntrl, $q){
  return {
      'request':function(request){
        if(!offlineCntrl.isOnline()){
          //there wont be a server call
          request.url='';
          //Abort the request
          request.timeout;
        }else{
          return request;
        }
      },
   
     'response':function(response){
        if(!offlineCntrl.isOnline()){
           var deferred = $q.defer();
           offlineCntrl.assignLocal(request).then(function(data){
            //Get the local data here.
            // Have to pass this data to my response
            // At this stage I am getting an error attached below
            response = data;
            return deferred.resolve(response);
          })
          return ( deferred.promise );
        }else{
         return response;
        }
     }
   }
})
.config(function($httpProvider){
  $httpProvider.interceptors.push('interceptors');
})
.factory('offlineCntrl', function($q, $timeout){
  return {
    isOnline: function(){
      return navigator.onLine;
    },
    assignLocal:function(request){
      var defer = $q.defer();
      $timeout(function(){
        defer.resolve({title:"local", body:"Local local data context"});
      })
      return defer.promise;
    }
  }
})
.factory('CloudSerivce', function($resource){
  return $resource('https://jsonplaceholder.typicode.com/posts/:id', {
    id:'@id'
  }, {
     get:{
       method:"GET",
			 isArray:false,
			 cancellable: true
     }
  })
})
.controller('mainCntrl', function($scope, CloudSerivce){
  $scope.data = {};

  $scope.getCloudService = function(){
    CloudSerivce.get({id:1}).$promise.then(function(data){
      //It should receive local data if there is no network
      $scope.data = data;
    }, function(err){
      console.log(err)
    })
  }

})
<html ng-app="servicetest">
  <body ng-controller='mainCntrl'>
    <h1>{{data.title}}</h1>
    <p>{{data.body}}</p>
    <button ng-click='getCloudService()'>
      GET ITEMS
    </button>
    <h4>Try the button disabling your internet connection</h4>
  </body>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular-resource.min.js"></script>
</html>