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

Javascript 在处理结果之前,等待承诺完成,javascript,angularjs,promise,Javascript,Angularjs,Promise,我有一个包装第三方API的服务,我正在使用它将数据检索到我的控制器中。我想在显示数据之前对数据进行一些处理,但我无法在承诺完成后实现这一点。在此之前,没有数据可处理 我尝试了几种不同的方法,但似乎都不管用: angular.module('myApp').controller('myController', function ($scope, MyService) { $scope.getData = function () { MyService.getData(myP

我有一个包装第三方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中的注释),然后将其传递回控制器显示。如果有什么不清楚的地方,我很乐意添加更多的评论


(对于架构方面的任何一般性反馈,我们都将不胜感激!)

所以我完全重构了一切,现在一切都正常了!其中一个问题是忘记了
$q.resolve()
$q.reject()
只能返回一个参数,而我假设我可以使用它们返回任意多的参数(就像使用匿名函数一样),以后调用
then()
将接收所有参数

如果有人感兴趣,我会在重构后发布我的代码,但我至少需要做的是替换如下调用:

operation.resolve(arg1, arg2, arg3);
为此:

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

并相应地调整接受这些参数的函数。

“这只在
$scope.queryResults=results处触发;
”正是您想要的,不是吗?如果
results
是一个空数组,那么这意味着
getData
确实导致了一个空数组。我猜是你的服务做了一些奇怪的事情,或者你只是没有收到你请求的任何数据。它确实返回数据,但需要几秒钟的时间<代码>然后(函数(结果){$scope.queryResults=results;}立即被一个空数组调用,然后在底层API调用完成后填充该数组。因此,MyService.getData返回了错误的承诺。如果您可以为它发布代码,它可能会揭示发生这种情况的原因。显然
ThirdPartyLibrary.getData
不会做您认为它会做的事情-任何信息从图书馆出去?