Angular 递归工厂方法

Angular recursive factory method

请问是否可以return递归工厂方法。我将展示一些代码,以便您可以更多地理解我。 我们有工厂:

angular.module('module')
.factory('synchronizationStatus', ['$http', 'apiBase', '$timeout', function ($http, apiBase, $timeout) {
    var service_url = apiBase.url;

    function syncCompleted ( correlationId ) {
        checkSync (correlationId)
            .then(function(response){
                $timeout(function() {
                    // if I get response.data true, i want to proceed to controller
                    if(response.data){
                        return "now I want to return result to controller"
                    }
                    else {
                        // check again
                        checkSync(correlationId)
                    }
                }, 500);

            })
    }

    function checkSync( correlationId ){
        return $http.get(service_url + query);
    }

    return {
        syncCompleted: syncCompleted
    };
}]);

这个工厂方法的主要思想是我不断地(每 500 毫秒)发送 ajax 请求到后端并检查一些操作是否完成,当它完成时我想发送承诺到控制器功能,看起来像这样:

function save( client ) {
        clients.addClient( client )
            .then( function(response) {
              synchronizationStatus.syncCompleted(response.data.CorrelationId);
            }, onSaveError)
            .then( redirectToList, onSaveError )
            .finally( unblock );
    }

在后端 return 符合我的工厂方法后,我想在我的控制器中执行其他功能。当然,我可以在我的控制器中进行递归,它会解决这个问题。虽然我必须在许多其他控制器中重用这个递归,所以我想重用这个方法。

使用自定义延迟(承诺),使用 Angular 的 $q。确保在工厂中注入 $q 依赖项并在工厂开始时创建延迟:

var deferred = $q.defer()

在承诺必须解决的地方,添加:

deferred.resolve();

并确保 return 在 syncCompleted 函数底部的承诺:

return deferred.promise;

此外,如果您还需要错误处理,可以添加 deferred.reject()。此外,如果需要,您可以向 reject()resolve() 添加参数。

作为替代方案,您可以在不使用 $q 的情况下实现相同的目标。 $timeout() 也是 return 一个承诺,如果你 return 在回调中给 then() 一个承诺,它会有点 'replace' 'parent'承诺。

是的,你应该可以做到这一点,但你需要稍微更改一下你工厂中的代码:

angular.module('module')
.factory('synchronizationStatus', [
    '$http', 
    'apiBase', 
    '$timeout', 
    function ($http, apiBase, $timeout) {
        var service_url = apiBase.url;

        function waitSyncCompletion( correlationId ) {
            return checkSync (correlationId)
            .then(function(response){
                 if (response.data) {
                     return "all done!";
                 }   

                 return $timeout(function() {
                     // check again
                     return waitSyncCompletion(correlationId);
                 }, 500);
            });
        }

        function checkSync( correlationId ){
            var query = '...'; // determine query
            return $http.get(service_url + query);
        }

        return {
            waitSyncCompletion: waitSyncCompletion
        };
    }
]);

然后在您的控制器中,您需要使用 return 以便您可以等待操作完成:

function save( client ) {
    clients.addClient( client )
    .then( function(response) {
         return synchronizationStatus.waitSyncCompletion(response.data.CorrelationId);
    })
    .then(function (result) { console.log(result); })
    .then( redirectToList )
    .catch( onSaveError )
    .finally( unblock );
}