功能抽象&承诺函数作为参数

时间:2015-01-08 09:26:42

标签: javascript promise

我正在尝试抽象下面的函数,以便我可以轻松地重用。函数基本上运行一个给定的函数,该函数最多返回5次promise或者直到promise被解析。 DataFn让我特别难过。它返回一个promise,但是当第一次失败后第二次执行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);

2 个答案:

答案 0 :(得分:3)

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

Promise代表值而不是操作 - 你的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
               });
    });
}

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

现在让我们再看看你的代码。通过在函数中包含$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
});

答案 1 :(得分:-3)

我带了这个函数,即使函数返回一个promise,它也能很好地工作。返回也是一个承诺,因此可以轻松处理结果。

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;
    };