我有一个json集合,我已经上传到我的firebase,这些网站和工具通过位于前者的数组相关联,指向后者中的键
"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/
答案 0 :(得分:5)
首先,你应该得到警报(其中3个),因为迭代按预期进行,但是getTool()函数的返回始终为null:它在promise被解析之前返回,而local tooitem变量是不再可以访问。
请记住,所有Firebase调用都是异步的。此外,这段代码:
var promise = angularFire(toolRef, $scope, "tool", {});
promise.then(function() {
alert("found tool " + toolId);
toolitem = $scope.tool;
}
将触发竞争条件:$ scope.tool与Firebase绑定,并且无法保证它将按特定顺序绑定,并且如果有足够的处理器时间将其推送到您的阵列,然后再解决另一个承诺。这就是为什么最好使用Firebase引用来监听值变化,而不是使用angularFire并将其显式绑定到范围变量。
我认为你的代码过于复杂,每次绑定范围变量时都不必创建新的Firebase引用(除非你以后要使用引用),使用angularFire:angulerFire可以接受String url因为它是第一个参数。
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", {});)
});