2015-01-08 19 views
1

我想抽象下面的函数,以便我可以轻松地重用。函数基本上运行一个给定的函数,该函数返回一个最大承诺5次或直到承诺解决。 DataFn让我特别难过。它返回一个承诺,但是当运行函数第一次失败后第二次执行时,它不会再尝试连接到服务器。如果我硬编码函数名称的作品,但作为传递的参数只能在开始工作。功能抽象和承诺函数作为参数

var persistentPromise = (function() { 
    var maxRetries = 0; 
    return function run(dataFn, messageObject) { 
     var deferred = $q.defer(); 
     dataFn.$promise.then(function (response) { 
       deferred.resolve(response); 
      }, 
      function (response) { 
       if(response == 503) { 
        if(++maxRetries < 6) { 
         messageService.emit(messageObject.warning); 
         $timeout(function() { 
          run(dataFn, messageObject); 
         }, 10000); 
        } else { 
         messageService.emit(messageObject.end); 
         deferred.reject(messageObject.na); 
        } 
       } 
      }); 
     deferred.promise.then(function (response) { 
      $scope.transactionData = { 
       transactions: kpiService.totalArrayAmountWithRange(response.rows, 2, 0, response.rows.length/2) + kpiService.totalArrayAmountWithRange(response.rows, 2, response.rows.length/2 + 1, response.rows.length) 
      }; 
      usSpinnerService.stop('loaderspin'); 
     }, function(response) { 
      usSpinnerService.stop('loaderspin'); 
      $scope.transactionData = { 
       transactions: response.na.msg 
      }; 
     }); 
    }; 
})(); 

/* calling the function */ 
persistentPromise(promiseFunction, someMessageObject); 
+0

这很难遵循。特别是,'dataFn'是什么?它没有被调用,它使用的唯一方面是'。promise'属性。 –

+0

这是一个函数,返回一个承诺的ajax调用 –

+0

那么它叫什么名字? –

回答

3

您可以将该代码完全分解为可重用的部分。请记住,承诺使用return语句并抽象化异步值的基础。

承诺代表值,而不是操作 - 你dataFn不是一个函数,但你只是在等待n次,每次10秒,实际上并不执行任何更多的调用函数的结果。

让我们先从一个retry

// fn - arbitrary function that returns a promise, in your case this is what 
// generates dataFn and __not__ dataFn itself. n - the number of retries 
function retry(fn, n){ 
    var reasons = []; // to keep rejection reasons 
    return $q.when().then(function retry(){ // start the chain 
     return fn(). // call the function 
       catch(function(err){ // if it failed 
        reasons.push(err); // accumulate reasons for failure of fn() 
        if(n-- <= 0) return $q.reject(reasons); // no more retries 
        return retry(); // recursive call, note the return 
       }); 
    }); 
} 

现在你可以重试的任何承诺返回函数任意次数,这是一个可分解位。

现在让我们再看看你的代码。在函数中包含$scope和uiSpinner有很多补充。让我们看看那个微调。

function spinUntil(fn){ 
    uiSpinnerService.start("loaderspin"); // start spinning, here and not outside 
    return fn().finally(function(){ // after FN resolves 
     uiSpinnerService.stop("loaderspin"); 
    }); 
} 

这将让你的整个代码看起来是这样的:

spinUntil(function(){ 
    return retry(promiseReturningFunction, 5); 
}).then(function(data){ // retries performed, spinner done 
    $scope.transactionData = data; // assign here, don't complect the scope and the fn. 
    // spinner and retries already done, $scope is not a concern of retry or spinUntil 
}); 
+0

我没有得到您的重试()函数错误,也没有这个函数计时器。 –

+0

您的函数也会在一次捕获后立即返回。不能优雅地解决。 –

+2

@ z.a。该函数的工作原理与广告一样 - 请参阅http://jsfiddle.net/ecL9vq9o/ - 将计数从5更改为3,例如看到它失败,因为没有足够的重试次数。 –

-3

我来到这个功能,它的伟大工程,即使该函数返回一个承诺。退货也是一种承诺,因此可以轻松处理结果。

function (fn, params, n) { 
     var deferred = $q.defer(); 
     (function retry() { 
      return fn(params).$promise 
       .then(function (response) { 
        deferred.resolve(response); 
       }, 
       function (response) { 
        if (n <= 0) { 
         deferred.reject(response); 
         return; 
        } 
        n--; 
        $timeout(function() { 
         return retry(); 
        }, 5000); 
       }); 
     })(); 
     return deferred.promise; 
    };