2013-08-16 28 views
1

我有一个JSON集我已上传到我的火力点,网站和工具,通过位于前那点键在后者AngularFire中的子承诺 - 通过ID选择相关的孩子?

"sites": { 
    "s001": { 
     "name": "ACT-105", 
     "description": "Intro Accounting", 
     "type": "course", 
     "thumbnail": "debate", 
     "toolCount": 4, 
     "tools" : ["t001","t002","t003"] 
    }, 
    "s002": { 
     "name": "ART-201", 
     "description": "Pottery Lab", 
     "type": "course", 
     "thumbnail": "sculpture", 
     "toolCount": 4, 
     "tools" : ["t001","t002","t003","t004"] 
    }, 
    "tools": { 
    "t001": { 
     "name": "main-tool", 
     "title": "Home", 
     "description": "Main tool", 
     "thumbnail": "home.jpeg" 
    }, 
    "t002": { 
     "name": "announce-tool", 
     "title": "Announcements", 
     "description": "System Announcements", 
     "thumbnail": "announcements.jpeg" 
    }, 

我打开一个网址,并承诺阵列有关;然后抓取数组中的当前网站及其相关工具的数组,然后打开另一个承诺来循环并获取所有相关工具。从警报中,它似乎只抓住一个工具然后退出。

angular.module("foo", ["firebase"]). 
    controller("MyCtrl", ["$scope", "angularFire", function($scope, angularFire) { 
    var dbRef = "https://sampledb.firebaseio.com"; 
    var siteRef = new Firebase(dbRef + "/sites/s003"); 
    var promise = angularFire(siteRef, $scope, "site", {}); 
    var sitetools = []; 
    promise.then(function() { 
     sitetools = $scope.site.tools; 
     alert("tools " + sitetools); 
    }).then(function() { 

     var toolList = []; 
     for (var i=0;i<sitetools.length;i++) 
     {  
      alert("tool " + sitetools[i]); 
      toolList.push(getTool(dbRef,toolId)); 
     } 
     $scope.tools = toolList; 
    }); 
    }]); 

    var getTool = function(dbRef,toolId) { 
    var toolitem; 
    var toolRef = new Firebase(dbRef + "/tools/" + toolId); 
    alert(toolRef); 
    var promise = angularFire(toolRef, $scope, "tool", {}); 
    promise.then(function() { 
     alert("found tool " + toolId); 
     toolitem = $scope.tool; 
    }); 
    return toolitem; 
    }; 

的小提琴是在这里:http://jsfiddle.net/5n9mj/1/

回答

5

首先,你应该已经得到了警报(其中3),因为迭代就如预期,但getTool的()函数返回总是null:它在promise解决之前返回并且本地tooitem变量不再可用。

请记住,所有Firebase调用都是异步的。此外,此代码:

var promise = angularFire(toolRef, $scope, "tool", {}); 
    promise.then(function() { 
    alert("found tool " + toolId); 
    toolitem = $scope.tool; 
} 

将引发竞争条件:$ scope.tool势必与火力地堡,并不能保证它会在一个特定的顺序进行约束,如果有足够的处理器时间推它在另一个承诺解决之前进入你的数组。这就是为什么使用Firebase引用监听值更改比使用angularFire并将其明确绑定到范围变量更好。

我认为你稍微复杂了一些代码,你不必在每次绑定你的范围变量(除非你打算使用后面的参考)和angularFire时创建新的Firebase引用:angulerFire可以接受字符串网址,因为它是第一个参数。

http://jsfiddle.net/oburakevych/5n9mj/10/

如果我是你,我想包工具功能集成到一个单独的控制器指令,从而使每个工具都会有它自己的范围内,这样的事情:

<ul ng-repeat="toolId in tools"> 
    <li><tool tool-id="{{toolId}}"/></li> 
</ul> 

var promise = angularFire(siteRef, $scope, "site", {}); 
promise.then(function() { 
     $scope.broadcast("event:SITE_INITIALIZED"); 
}); 

.controller("MyCtrl", ["$scope", "angularFire", '$timeout', function($scope, angularFire, $timeout) { 
    $scope.$on("event:SITE_INITIALIZED", function() { 
      angularFire(siteRef + "/item/" + $scope.itemId, $scope, "item", {});) 
    }); 
+0

感谢最后一个提示与scope.broadcast - 我没有真正理解你的例子,直到我读了Angular文档:http://docs.angularjs.org/api/ng.$ro​​otScope.Scope –

+0

另外,我看到你已经包括$超时但它没有被使用/进一步定义;该功能的文档不太清楚;是否包含了您的angularFire调用自动使用的$ timeout?或者是否将它作为稍后指定的占位符? –

+0

@PatrickHaggood我在jsfiddle示例中使用了超时:http://jsfiddle.net/oburakevych/5n9mj/10/。 angularFire不需要$超时,但我注意到 - 当新项目添加到工具时,不会触发摘要:$ scope.tools.push(snapshot.val());因此,我必须在$ push()之后放置$ scope。$ apply(),或者将其包装在$ timeout中,这会触发$自动应用。这可能是Firebase家伙的问题 - 这似乎是一个错误。 –