Angularjs $ http返回结果,但没有使用$ q.defer完成

时间:2014-12-04 22:23:01

标签: javascript angularjs angular-promise angular-http

我有一个角度问题,即使我使用$ q.defer功能,结果会在实际完成之前返回到我的控制器。我的服务中有以下功能

      getFileInfo : function (fulfillmentId)
        {
            var pdfResults = [];
            var jpgResults = [];
            var orderDetails = {};
            var deferred = $q.defer();


            $http.get(appConstants.api_url + '/references/' + fulfillmentId + '/files?max=2000')
                . then (function (fileResults)
                {
                    angular.forEach(fileResults.data.entities,function(value)
                    {
                        if(value.file.extension == 'pdf')
                        {
                            pdfResults.push({files : value});

                        }

                        if(value.file.extension == 'jpg')
                        {
                            jpgResults.push({files : value});
                        }
                    });

                    orderDetails.jpgResults = jpgResults;

                    return pdfResults;

                })
                .then (function (pdfResults)
                {
                    angular.forEach(pdfResults,function(value,key)
                    {

                        var fileUuid = value.files.file.file_uuid;

                        return $http.get(appConstants.api_url + '/resources/' + fileUuid + '/tags')
                            .then (function (preflightResults)
                        {

                            var deserializeJson = [];
                            deserializeJson.push(angular.fromJson(preflightResults.data.entities[0].resource_json));
                            var formatedPreflightResults = localAPI.addUIMessages(deserializeJson);

                            pdfResults[key].preflightResults = formatedPreflightResults;
                        });

                    });

                    orderDetails.pdfResults = pdfResults;

                    deferred.resolve(orderDetails);
                });


            return deferred.promise;


        }

我从我的控制器调用它就像这样:

 conformAPI.getFileInfo($scope.fulfillmentId)
        .then (function (results)
        {
            console.log(results);
            console.log(results.pdfResults[0]);
            console.log(results.pdfResults[0].preflightResults)

        });

我遇到的问题是我正在做的最后一个控制台日志是未定义的。其他一切都很好地回归结果。第一个和第二个控制台就像那里有preflightResults对象,但它似乎有点迟了。我想通过使用$ q.defer,在一切都完成之前不会返回任何内容。关于如何解决这个问题的任何想法?

2 个答案:

答案 0 :(得分:1)

看起来你不是在等待“getFile”获取请求的结果。 我稍微重构了你的代码。它可能不起作用,因为我无法运行它,但你应该看到我的观点。

getFileInfo: function (fulfillmentId) {

var pdfResults = [];
var jpgResults = [];
var orderDetails = {};
var deferred = $q.defer();

function getByFileId(fileUuid, preflightResults) {

    return $http.get(appConstants.api_url + '/resources/' + fileUuid + '/tags')
        .then(function (preflightResults) {
        var deserializeJson = [];
        deserializeJson.push(angular.fromJson(preflightResults.data.entities[0].resource_json));
        var formatedPreflightResults = localAPI.addUIMessages(deserializeJson);

        return formatedPreflightResults;
    });
}

function getFiles(pdfResults) {

    var subDefer = $q.defer();
    var current = 0;

    angular.forEach(pdfResults, function (value, key) {
        current += 1;
        var fileUuid = value.files.file.file_uuid;

        getByFileUuid(fileUuid, preflightResults)
            .then(function (results) {

            pdfResults[key].preflightResults = results;

            // need to know when done with all
            if (pdfResults.length === current) {
                subDefer.resolve(pdfResults);
            }
        });
    });

    return subDefer.promise;
}

$http.get(appConstants.api_url + '/references/' + fulfillmentId + '/files?max=2000')
.then(function (fileResults) {

    angular.forEach(fileResults.data.entities, function (value) {

        if (value.file.extension == 'pdf') {
            pdfResults.push({ files: value });
        }

        if (value.file.extension == 'jpg') {
            jpgResults.push({ files: value });
        }
    });

    orderDetails.jpgResults = jpgResults;
    return pdfResults;

}).then(getFiles).then(function(pdfResults) {

    orderDetails.pdfResults = pdfResults;
    deferred.resolve(orderDetails);
});

return deferred.promise;

}

答案 1 :(得分:0)

你太早解决了你的承诺。

因为你的第一个然后()只返回一个对象,所以第二个然后()将立即跟随。所以这就是代码正在做的事情(粗糙的伪代码):

$ http.get()。然后(首先返回$ http.get);

一旦您开始获取第一个文件,就会返回(return $http.get(appConstants.api_url + ...)。此时,只有顶部的第一个$ http.get肯定已经解决了。您可能会看到第二个$ http.get(第一个文件)很快就会解决,但您还没有再启动任何更多文件的$ http.gets。

您可能在此代码中的目标是,如果删除中间返回以便生成所有$ http.gets,则为:

$ http.get()。然后(启动所有$ http.gets并解决promise);

只要您循环浏览所有文件并使用$ http.get启动它们,就可以解决承诺。这有同样的问题 - 承诺得到解决太早。所有的收益都已发出,但你无法确定它们是否已经回来了。

你能做的是:

$ http.get()。然后(启动所有$ http.gets并在完成所有操作后解决承诺);

例如,代替pdfResults上的forEach,您可以将它们映射到$ http.get的数组:filePromises = pdfResults.map(function(e)$ http.get(e))

然后你会在你现在有deferred.resolve(orderDetails)的末尾return $q.all(filePromises)