2013-08-16 78 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傢伙的問題 - 這似乎是一個錯誤。 –