在处理结果之前等待承诺完成

时间:2015-12-11 10:16:02

标签: javascript angularjs promise

我有一个包含第三方API的服务,我将其用于将数据检索到我的控制器中。我希望在显示数据之前进行一些处理来转移数据,但是在承诺完成之后,我无法解决如何实现这一问题。在此之前,没有数据需要处理!

我尝试了几种不同的方法,但似乎都没有用:

angular.module('myApp').controller('myController', function ($scope, MyService) {
    $scope.getData = function () {
        MyService.getData(myParams)
            .then(function (results) {
                $scope.queryResults = results;
                // Can't do processing here, data hasn't been retrieved yet
            }, function (err) {
                $scope.alerts.push({ msg: 'Unable to get data', type: 'danger' });
            });
    }

    $scope.$watch('queryResults', function(newVals) {
        // Can't do processing here either, this only fires at
        // "$scope.queryResults = results;"
        // above where "results" is still an empty array
    });
};

服务:

angular.module('myApp').service('MyService', ['$q', function($q) {
    return {
        getData: function (params) {
            var operation = $q.defer();
            ThirdPartyLibrary.getData(params, { callback: function(err, results) {
                if (err == null ) {
                    operation.resolve(results);
                } else {
                    operation.reject(err, results);
                }
            }});
            return operation.promise;
        }
    }
}]);

这一定是一件非常普遍的事情,但我在谷歌上找不到多少 - 尽管我可能会在寻找错误的东西!

修改

好的,所以我已经重构了很多东西,而潜在的问题似乎仍然是我的承诺链在数据从链中的早期返回之前正在进行。这是新代码:

angular.module('myApp').service('MyService', ['MyWrapperService', function(MyWrapperService) {
    var getDataForFilter = function(myApi, filter) {
        var processedResults = {};
        // This is the chain I'm having problems with
        return MyWrapperService.getRelevantKeys(myApi, filter).then(MyWrapperService.getDetailsForKeys).then(function(results){
            //do some processing here
            return processedResults;
        }, function(errors) {
            return errors;
        });
    };

    return {getDataForFilter: getDataForFilter};
}]);

angular.module('myApp').service('MyWrapperService', ['$q', function($q) {
    var getRelevantKeys = function(myApi, filter) {
        var operation = $q.defer();
        myApi.getKeys({'filter': filter, 'callback': function (err, results) {
            if (err == null) {
                    // This does get called correctly, but not until after the rest of the chain has been called.
                operation.resolve(myApi, results, filter);
            } else {
                operation.reject(err, results);
            }
        }
    };
    var getDetailsForKeys = function(myApi, keys, filter) {            
        var operation = $q.defer();
        var promises = [];
        var details = [];
        var errors = [];

        angular.forEach(keys, function (val) {
            // Get the data for each key. ***When this is called, 'keys' is still undefined.***
            promises.push(getDataForKey(myApi, val, filter).then(function(result){
                details.push(result);
            }, function(err, result) {
                errors.push(err);
            }));
        });

        $q.all(promises).then(function() {operation.resolve(details);}, function() {operation.reject(errors)});
        return operation.promise;
    };
    var getDataForKey = function(myApi, key, filter) {
        var operation = $q.defer();
        myApi.getDetail(key, {
            'filter': filter,
            'callback': function(err, results) {
                if (err == null) {
                    operation.resolve(myApi, results, activity);
                } else {
                    operation.reject(err, results);
                }
            }
        });
        return operation.promise;
    };

    return {
        getRelevantKeys: getRelevantKeys,
        getDetailsForKeys: getDetailsForKeys,
        getDataForKey: getDataForKey,
    };
}]);

不幸的是,API会让我尝试做一些啰嗦的事情,但是我得到了与过滤器相关的所有数据库密钥,然后获取这些密钥的所有值,然后转动数据(getDataForFilter中的注释)在传回控制器之前显示。如果有什么不清楚,我很乐意添加更多评论。

(对于架构的任何一般反馈,我们将非常感激!)

1 个答案:

答案 0 :(得分:0)

所以我完全重构了一切,现在一切正常!其中一个问题是忘记$q.resolve()$q.reject()只能在我假设我可以返回我想要的多个参数时返回一个参数(就像你可以使用匿名函数一样)以后拨打then()会收到所有电话。

如果有人有兴趣,我会在重构后发布我的代码,但我需要做的最低限度是替换这样的调用:

operation.resolve(arg1, arg2, arg3);

用这个:

operation.resolve({'arg1': arg1, 'arg2': arg2, 'arg3':arg3});

并相应地调整采用这些参数的函数。