2015-01-08 3 views
1

쉽게 재사용 할 수 있도록 아래 함수를 추상화하려고합니다. 함수는 기본적으로 약속을 최대 5 회 또는 약속이 해결 될 때까지 반환하는 함수를 실행합니다. DataFn에서 특히 힘든 시간을 보내고 있습니다. 그것은 약속을 반환하지만 run 함수가 첫 번째 실패 이후 두 번 실행되면 서버에 다시 연결하려고 시도하지 않습니다. 함수 이름을 하드 코딩하면 작동하지만 전달 된 매개 변수는 처음부터 작동합니다.함수 추상화 및 매개 변수로 함수 약속

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를 포함하면 많은 편견이 있습니다. 그 회 전자를 보자.

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

retry() 함수 오류가 발생하지 않으며이 함수에는 타이머가 없습니다. –

+0

귀하의 기능도 즉시 하나의 캐치 후에 반환됩니다. 정상적으로 해결되지 않습니다. –

+2

@ z.a. 이 기능은 광고로 작동합니다. http://jsfiddle.net/ecL9vq9o/를 참조하십시오. 예를 들어 카운트를 5에서 3으로 변경하면 재시도가 충분하지 않아 실패합니다. –

-3

내가 함수가 약속을 반환하는 경우에도 좋은 작품이 기능을 함께 제공 : 전체 코드를 할 것

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

은 같은 모양. 리턴은 또한 약속이기 때문에 결과를 쉽게 처리 할 수 ​​있습니다.

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; 
    }; 
관련 문제