【问题标题】:Angular promise failure on timeout角度承诺超时失败
【发布时间】:2017-03-16 05:40:37
【问题描述】:

如果我的 promise 未能在 300 毫秒内返回结果,我希望我的 promise 失败,如果失败,我希望调用另一个 promise,它将执行一个执行时间更短的默认函数。

到目前为止我已经尝试过 -

    $timeout(function(){
      GetAirMsg.get({mDate: $filter('date')($scope.realdateFrom,'ddMMyy'),
                mDateO: $filter('date')($scope.realdateFrom,'yyyyMMdd'),
                mDateD: $filter('date')($scope.realdateFrom,'dd-MMM-yyyy'),
                acode: $filter('uppercase')($scope.air),
                offset: offsetInt}).$promise.then(function(result){
                /* result evaluation */    
            });
      },300).then(function(data){

         console.log('Timed out! sorry!');
         /*execute another promise with shorter execution time */
         console.log('data : '+data);

      },function(error){

        //console.log('Timed out! sorry!');

    });

服务是 -

angular.module('example').factory('GetAirMsg',['$resource',function($resource){
return $resource(serverBaseUrl + '/getAirMsg/:mDate/:mDateO/:mDateD/:acode/:offset', 
        {mDate: '@mDate',mDateO: '@mDateO',mDateD: '@mDateD',acode: '@acode',offset: '@offset'}, {
            get: {method: 'GET', isArray: false}
        });
}])

服务 GetAirMsg 执​​行一个查询,该查询占用了几个值的大量时间,该查询目前已尽可能优化。所以我想要一个只返回基本信息的后备。

现在面临的问题 - 控制台总是显示 '时间到!对不起! 数据:未定义'。对于在该时间范围内未返回值的情况,请求仍处于挂起状态。

【问题讨论】:

  • 如果你想在失败时执行另一个 Promise。在.then() 之后使用.catch()。而不是在.then()之后的(err)
  • @ReyanTropia 如果我的承诺未能在 300 毫秒内返回结果,我该如何让我的承诺失败,因为现在呼叫在我的网络中仍处于挂起状态?我是 Angular 的新手,我不知道该怎么做。 TIA :)
  • 这很奇怪。您的请求状态仍然是pending?那么 .then(data) 根本不应该触发。顺便说一句Promises 不可取消。只能取消Observables
  • @ReyanTropia 现在无论请求的状态如何,都会显示 console.log 消息

标签: angularjs timeout angular-promise


【解决方案1】:

您可以使用$resourcetimeout 设置。查看示例用法here

作为您的代码示例;

服务:

angular.module('example').factory('GetAirMsg',['$resource',function($resource){
return $resource(serverBaseUrl + '/getAirMsg/:mDate/:mDateO/:mDateD/:acode/:offset', 
        {mDate: '@mDate',mDateO: '@mDateO',mDateD: '@mDateD',acode: '@acode',offset: '@offset'}, {
            get: {method: 'GET', isArray: false, timeout: 300}
        });
}])

控制器:

GetAirMsg.get({mDate: $filter('date')($scope.realdateFrom,'ddMMyy'),
        mDateO: $filter('date')($scope.realdateFrom,'yyyyMMdd'),
        mDateD: $filter('date')($scope.realdateFrom,'dd-MMM-yyyy'),
        acode: $filter('uppercase')($scope.air),
        offset: offsetInt}).$promise
    .then(function(result){
        /* result evaluation */    
    })
    .catch(function() {
        console.log("error!");
    });

【讨论】:

  • 这会导致请求状态在超时的情况下变为取消但我的查询仍在运行,这会导致其他请求保持等待状态并且我的应用程序正在崩溃
  • 此问题与您的问题无关。这是关于你的 REST API。您可以为 REST 请求(服务器端)设置超时,或者通过调用特殊的 REST 方法将 REST API 设置为允许取消。您的 REST API 使用哪种语言/系统?
  • 我正在想办法为我的项目在后端设置一个计时器。我们正在使用组织特定的软件包,所以我试图弄清楚这一点。我正在使用python作为后端。感谢你的快速回复。您的解决方案效果很好。
【解决方案2】:

显示该控制台的原因是因为timeout 函数成功运行,并且由于timeout 没有返回任何数据,data 将是undefined

试试这个。

控制器代码:

$scope.isFirstCallSuccess = false;

$timeout(function(){
  GetAirMsg.get({
      mDate: $filter('date')($scope.realdateFrom,'ddMMyy'),
      mDateO: $filter('date')($scope.realdateFrom,'yyyyMMdd'),
      mDateD: $filter('date')($scope.realdateFrom,'dd-MMM-yyyy'),
      acode: $filter('uppercase')($scope.air),
      offset: offsetInt})
    .$promise
    .then(function(result){
    /* result evaluation */    
    $scope.isFirstCallSuccess = true; // updating only if call success
  },function(error){
    // API call was failure even before the timeout
  });
  },300).then(function(){
  if(!$scope.isFirstCallSuccess){
    //the call was failure. the value is still false
    /*execute another promise with shorter execution time */
    console.log('Timed out! sorry!');
  }

});

【讨论】:

    【解决方案3】:

    显示该控制台的原因是因为timeout 函数成功运行,并且由于timeout 没有返回任何数据,data 将是undefined

    试试这个。

    控制器代码:

    $scope.isFirstCallSuccess = false;
    
    $timeout(function(){
    	GetAirMsg.get({
    		mDate: $filter('date')($scope.realdateFrom,'ddMMyy'),
    		mDateO: $filter('date')($scope.realdateFrom,'yyyyMMdd'),
    		mDateD: $filter('date')($scope.realdateFrom,'dd-MMM-yyyy'),
    		acode: $filter('uppercase')($scope.air),
    		offset: offsetInt})
    		.$promise
    		.then(function(result){
    		/* result evaluation */    
    		$scope.isFirstCallSuccess = true; // updating only if call success
    	}, ,function(error){
    		// API call was failure even before the timeout
    	});
    },300).then(function(){
    	if(!$scope.isFirstCallSuccess){
    		//the call was failure. the value is still false
    		/*execute another promise with shorter execution time */
    		console.log('Timed out! sorry!');
    	}
    
    });

    编辑:

    方法:再创建一项服务来取消承诺。如果在超时结束前未完成,请使用该服务取消

    服务:

    function cancel( promise ) {
    //it will cancel the promise only the promise is still active
      if (promise) {
        promise.reject();
      }
    }
    

    控制者:

    $scope.gettingAirMsg = GetAirMsg.get({
        mDate: $filter('date')($scope.realdateFrom,'ddMMyy'),
        mDateO: $filter('date')($scope.realdateFrom,'yyyyMMdd'),
        mDateD: $filter('date')($scope.realdateFrom,'dd-MMM-yyyy'),
        acode: $filter('uppercase')($scope.air),
        offset: offsetInt})
        .$promise
        .then(function(result){
            //success
            }, ,function(error){
    
        });
    
     $timeout(function(){
       yourService.cancel($scope.gettingAirMsg) 
       //it will cancel the promise only the promise is still active
       // if the promise ends before 300ms the cancel call will not pass active promise
     },300)
    

    【讨论】:

    • 对我来说真的不起作用 - 在 300 毫秒内成功返回值的 promise 运行良好,但对于那些不成功的 promise,请求调用仍处于挂起状态,因此我的网络被阻塞我的应用程序崩溃了。所以基本上承诺在超时的情况下无法返回“失败”。我可能遗漏了一些我只是不知道它是什么的东西。
    • 更新了答案。立即查看
    • 酷 :) 你可以使用reject()resole()。两者都可以。
    猜你喜欢
    • 2016-04-24
    • 2019-02-15
    • 2016-10-03
    • 1970-01-01
    • 1970-01-01
    • 2017-11-01
    • 1970-01-01
    • 2015-11-22
    • 2016-08-31
    相关资源
    最近更新 更多