简体   繁体   English

如何中止或取消Angularjs $ resource请求并通过本地数据覆盖响应

[英]How to abort or cancel an Angularjs $resource request and override the response by a local data

In one of my new projects I am using AngularJS $resources for http calls. 在我的一个新项目中,我将AngularJS $ resources用于http调用。 I have requirement to show local data (from SQLite) when there is no internet connection. 我需要在没有互联网连接时显示本地数据(来自SQLite)。

I have clustered my obstacles by the following steps, and created sample code down below 我通过以下步骤将障碍归类,并在下面创建了示例代码

  • Step 1: On click of the button call the $resource //Done 步骤1:点击按钮,调用$ resource //完成
  • Step 2: Before sending the request check if machine connected to network //Done 步骤2:在发送请求之前,请检查计算机是否已连接到网络//完成
  • Step 3: If network connected, get the response //Done 步骤3:如果网络已连接,请获取响应//完成
  • Step 4 : If no network then abort the request//Done 步骤4 :如果没有网络,则中止请求//完成
  • Step 5: If no network respond the local data to the $resource promise -- Not sure how to do that. 步骤5:如果没有网络响应$ resource promise响应本地数据-不确定如何执行此操作。

 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> 

I am getting an error when I try to return the response with deferred promise event. 我尝试返回带有延迟的Promise事件的响应时遇到错误。

 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)

I can do it by bubbling up a $rootScope emitter and catch it within the controller, but I believe the easiest way is to hack the ngResource (CloudService $promise event) response after aborting the request. 我可以通过冒泡$ rootScope发射器并将其捕获到控制器中来完成此操作,但是我认为最简单的方法是在中止请求后修改ngResource(CloudService $ promise事件)响应。 So that I can keep the controller getCloudService function as it is, which can work on offline and online mode. 这样我就可以保持控制器的getCloudService函数不变,该函数可以在脱机和联机模式下工作。

You made a mistake here! 您在这里犯了一个错误!

$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
    })
  }

Also to handle the error case you should be using somehting like this? 另外,要处理错误情况,您应该使用这种方式吗?

 $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 
        });
 }

Need to do something like that 需要做这样的事情

.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;
          }
        }
      })

The following work around worked out. 解决了以下工作。

 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> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM