7

有没有办法通过 AngularJS 中的函数调用未知数量的 API 调用到 URL get(),并将它们全部添加到模型($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,并为每个 UID 创建一个temp对象,该对象填充一个uid,然后是一个accountInfo对象,然后是一个files对象。设置temp对象后,我将其推送到myDropbox阵列上。循环完成后,我将 dropboxAccounts 模型设置myDropbox$scope. 我是 Angular 的新手,但我很确定这至少是正确的想法。幸运的是,我以正确的顺序获得了以下数据:

{"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"}]
}

奇怪的是,只有我的一个 UID 得到更新。我知道循环正在正确通过,因为我有两个 UID,如果我在循环开始时发出警报,我会得到两个循环。我认为第二个没有被填充的原因是因为 push 语句没有等待两个承诺都通过。如何确保在分配myDropbox$scope变量之前等待每个 AJAX 调用完成?

4

1 回答 1

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(我们稍后会到达工厂)。在这个控制器内部,我们将两个模型分配给$scopedropboxAccountsdropboxFiles. 请注意,我最初的愿望是在我的 AngularJS 应用程序中拥有一个模型。虽然这是可能的......我选择反对它,因为我发现很难区分我的两种类型的 JSON 返回。一个返回帐户元数据,另一个返回该帐户的文件数组。我本来希望将所有这些都放在一个模型下并按uid参数排序,但发现如果不更改我的 RESTful 端点输出的 JSON,这是不可能做到的。最后,我选择了两个独立的模型,这样我可以更轻松地使用它们(直到我找到一种根据一个通用参数组合它们的方法)。

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

我学到的是

AngularJS is really tough. This particular issue has taken me two days of debugging and trying again and again. I have been told that while the learning curve to this front-end MVC framework is pretty steep, the payoff is well worth it. I suppose we shall see...

Resources

于 2013-04-17T21:08:15.940 回答