AngularFire的子承诺 - 通过ID选择相关的孩子?

时间:2013-08-16 23:42:32

标签: angularjs firebase promise angularfire

我有一个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/

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", {});)
    });