多个AngularJS将请求转换为一个模型

时间:2013-04-17 15:39:23

标签: javascript jquery ajax angularjs

有没有办法通过AngularJS中的get()函数调用对URL的未知数量的API调用,并将这些调用全部添加到模型($scope变量)中。到目前为止我所做的是以下内容:

if(theUIDS != "") {
    var myDropbox = [];

    for(i = 0; i < theUIDS.length; i++) {
        var temp = {};

        temp.uid = theUIDS[i];

        $http({ url: '/dropbox/accounts/get', method: 'GET', params: { uid: theUIDS[i] }}).success(function(acctData) {
            temp.accountInfo = acctData;
        });

        $http({ url: '/dropbox/files/get', method: 'GET', params: { uid: theUIDS[i] }}).success(function(fileData) {
            temp.files = fileData;
        });

        myDropbox.push(temp);
    }

    $scope.dropboxAccounts = myDropbox;
}

我检查是否有任何UID,并为每个创建一个temp对象,其中填充了uid,然后是accountInfo对象,然后是{{1}对象。设置files对象后,我将其推送到temp数组。循环完成后,我将dropboxAccounts模型设置为myDropbox中的myDropbox变量。我是Angular的新手,但我很确定这至少是正确的想法。幸运的是,我按正确顺序得到以下数据:

$scope

奇怪的是,我的UID中只有一个会更新。我知道循环是正确的,因为我有两个UID,如果我在开始时警告循环,我得到两个循环。我认为第二个没有被填充的原因是因为推送声明不等待两个承诺通过。在将{"uid":"332879"} {"uid":"155478421", "accountInfo":{ "country":"US", "display_name":"Patrick Cason", "name":"Second Dropbox", "quota_normal":1174504, "quota_shared":0, "quota_total":2147483648, "referral_link":"https://www.dropbox.com/referrals/NTE1NTQ3ODQyMTk?src=app9-203957", "uid":155478421}, "files":[{ "created_at":"2013-04-17T15:13:46Z", "directory":true, "dropbox_user_id":26, "fileType":"Folder", "id":198, "name":"Photos", "path":"/Photos", "rev":"10edb44f9", "size":"-", "updated_at":"2013-04-17T15:13:46Z"}] } 分配给myDropbox变量之前,如何确保等待每个AJAX调用完成?

1 个答案:

答案 0 :(得分:15)

简介

我是AngularJS的新手,所以这个解决方案非常适合正在进行的工作。我认为,因为我一直在努力学习更多关于它的事情,其他人也可能处于相同的位置。话虽如此,我不仅要发布我的答案,还要解释我在代码背后的想法。如果有人觉得答案可以得到改善,我很乐意得到任何反馈。

最终守则

以下是我用来使一切正常运行的代码:

var app = angular.module('myApp', []);

app.controller('DropboxCtrl', function($scope, dropbox) {
    $scope.dropboxAccounts = dropbox.getAccounts();
    $scope.dropboxFiles = dropbox.getFiles();
});

app.factory('dropbox', function($http, $q) {
    var theUIDS = [12345,67890];

    return {
        getAccounts: function() {
            var promises = [];

            for(i = 0; i < theUIDS.length; i++) {
                promises.push($http({
                    url: '/dropbox/accounts/get', 
                    method: "GET",
                    params: { uid: theUIDS[i] }
                }));
            }

            return $q.all(promises);
        },
        getFiles: function() {
            var promises = [];

            for(i = 0; i < theUIDS.length; i++) {
                promises.push($http({
                    url: '/dropbox/files/get', 
                    method: "GET",
                    params: { uid: theUIDS[i] }
                }));
            }

            return $q.all(promises);
        }
    }
});

基本算法

我们首先声明一个模块myApp并将其保存在变量app中...注意我们传递的空数组,这通常是任何可能或可能的进一步要求的参数不能从其他模块继承。

声明我们的模块之后,我们需要创建一个相应的控制器,它将成为所有交互发生的网关。在这种情况下,我们需要访问相对于我们的控制器的$scope变量(不是相对于应用程序本身)。我们还声明了这个控制器与哪个工厂相关,在我的例子中它是dropbox(我们马上就会到工厂)。在此控制器内部,我们为$scope分配了两个模型:dropboxAccountsdropboxFiles。请注意,我最初的愿望是在我的AngularJS应用程序中有一个模型。虽然这是可能的......我选择反对它,因为我发现很难区分我的两种类型的JSON返回。一个返回帐户元数据,另一个返回该帐户的文件数组。我希望在一个模型下拥有所有这些并按uid参数排序,但发现如果不更改我的RESTful端点输出的JSON,这是不可能的。最后,我选择了两个单独的模型,这样我就可以更轻松地使用它们(直到找到根据一个公共参数组合它们的方法)。

最后,我们创建了一个存储我的AJAX函数的工厂(使用$http进行实际的AJAX调用,使用$q来处理promises)。我有两个函数:(记住从我的控制器调用)getAccountsgetFiles。他们每个人都有一个名为promises的数组,它将存储我$http次调用的承诺。我在for循环中运行这些调用,它将查看我在AJAX调用中使用的theUIDS中的每个项目,然后将其推送到promises数组。最后,我们有$q,它将等待promises数组中的所有AJAX调用成功完成,然后将一个大承诺中的所有数据返回给我们的控制器并将其分配给{{1 }}

我学到了什么

AngularJS非常强硬。这个特殊问题需要我两天的调试和反复尝试。有人告诉我,虽然这个前端MVC框架的学习曲线非常陡峭,但是回报非常值得。我想我们会看到......

资源