簡體   English   中英

在AngularJS服務中使用Promises

[英]Working with Promises in AngularJS service

我正在將一些代碼從Silverlight遷移到AngularJS。 我的Silverlight代碼基本上會嘗試訪問Web服務。 如果失敗,則將稍等片刻,然后重試。 它將嘗試三遍。 我現在正在嘗試在AngularJS中執行此操作。

據我了解,我應該使用AngularJS服務來訪問我的Web服務。 根據我的理解,使用了諾言。 目前,我提供以下服務:

'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)如果嘗試了3次失敗都失敗了。

有人可以告訴我如何在承諾的世界中解決這種情況嗎?

讓我在下面的注釋中發布代碼如何執行該操作:

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服務的實例,自己創建一個延遲對象(一個Promise)。
  2. 將其作為參數傳遞給attemptToGetRecent函數,該函數將繼續遞歸調用自身,直到工作量過多為止。
  3. 函數attemptToGetRecent將嘗試調用服務器,如果成功,它將使用數據解析您的承諾。 如果呼叫失敗,將最多調用3個計時器,然后拒絕您的承諾

此代碼的使用者將以這種方式使用它:

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

為了便於閱讀,我刪除了使用控制台的日志記錄。 當然可以添加。 這也是一個好習慣,不要以$開頭來命名您自己的服務,這是為角度服務保留的。

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

您可以注入$ 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);
    });
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM