在AngularJS服务中使用Promise

时间:2014-08-14 13:08:14

标签: javascript angularjs

我正在将一些代码从Silverlight迁移到AngularJS。我的Silverlight代码基本上会尝试访问Web服务。如果失败了,它会稍等一会再试一次。它会尝试这三次。我现在正试图在AngularJS中这样做。

根据我的理解,我应该使用AngularJS服务来点击我的网络服务。根据我的理解,使用了承诺。这时,我有以下服务:

'use strict';
myApp.service('$myService', function($rootScope, $http) {
  this.queryAttempt = 0;
  this.findRecent = function() {
    this.queryAttempt = 0;
  };

  this.attemptToGetRecent = function() {
    try {
      this.queryAttempt = this.queryAttempt + 1;
      if (this.recentQueryAttempt < 3) {
        $http.get('http://www.someserver.com/endpoint');        
      } else {
        console.log('signal failure');
      }
    } catch (ex1) {
      console.log('Error Finding Recent (2).');
    }
  };
});

由于使用了承诺,我有点迷失。在Silverlight中,我创建了一些事件。我的控制器将调用$ myService.findRecent()。我想检测成功和失败。但是,我还需要一些重试逻辑。如果我不需要重试逻辑,我只需在findRecent函数中使用return $ http.get(...)。但是,由于需要重试逻辑,我不知道如何构建我的承诺,以便控制器知道a)成功,b)如果尝试了三次尝试失败,则失败。

有人能告诉我如何在承诺的世界中解决这个问题吗?

2 个答案:

答案 0 :(得分:1)

让我发布代码如何使用下面的评论:

myApp.service('myService', function($rootScope, $http, $q) {

    var findRecent - function() {

        var deferred = $q.defer();

        attemptToGetRecent(0, deferred);

        return deferred.promise;
    };


    var attemptToGetRecent = function(count, deferred) {
        $http.get('http://www.someserver.com/endpoint')
             .success(function (response) {
                deferred.resolve(response);
             })
             .error(function() {
                if (count >= 3) {
                    deferred.reject();
                } else {
                    attemptToGetRecent(count++, deffered);
                }
             });
    };
});
  1. 在您的服务获取$q服务实例中,创建延迟对象 (承诺)你自己。
  2. 将其作为参数传递给attemptToGetRecent函数 继续以递归方式调用自己,直到努力的次数也是如此 高。
  3. 函数attemptToGetRecent将尝试调用服务器,如果 成功它解决了你对数据的承诺。如果呼叫失败, 它将被再次调用最多3个定时器然后拒绝你的承诺
  4. 此代码的使用者将以这种方式使用它:

    myService.findRecent()    
        .then(function (data) {
            console.log(data);
            $scope.videos = data.feed.entry;
          }, function() {
            console.log("error");
          });       
        }; 
    

    为了便于阅读,我使用控制台删除了日志记录。当然可以添加。另外一个好习惯是不用领先的$命名你自己的服务,这是为角度服务保留的。

    工作示例: http://codepen.io/anon/pen/KnCFJ

答案 1 :(得分:0)

你可以注入$ q并使用它来制定你自己的诺言并创建一个递归函数来处理这些尝试。

以下是一些应该有用的代码:

'use strict';
myApp.service('$myService', function ($rootScope, $http, $q) {
    this.getRecent = function(){
        var deferred = $q.defer();
        var attempts = 0;
        (function queryRecent(attempts, error){
            if(attempts >= 2){
                // the $http.get() failed 3 times
                deferred.reject(error);
            }else{
                $http.get('http://www.someserver.com/endpoint').then(function(response){
                    // success -> resolve any data you want
                    deferred.resolve({
                        attempts: attempts,
                        response: response
                    });
                }).catch(function(error){
                    // failed, retry the queryRecent recursive function
                    queryRecent(attempts + 1, error); // pass attempts + 1 and the error object
                });
            }
        })(attempts, ''); // initially pass 0 and '' to the queryRecent recursive function
        return deferred.promise;
    };
});

myApp.controller('MyCtrl', function($scope, $myService){
    $myService.getRecent().then(function(data){
        // success -> use data
        console.log(data);
    }).catch(function(error){
        // the $http.get() failed 3 times
        console.log(error);
    });
});
相关问题