【问题标题】:angularFire startAt querying and binding deletes new dataangularFire startAt 查询绑定删除新数据
【发布时间】:2015-01-09 11:32:01
【问题描述】:

应用程序显示特定时间段的轮班。 firebaseConn.getShifts 是获取给定时间段内 shiftData 的 API 函数。

版本: 火力基地:2.0.6 angularFire:0.9.0(也与 0.8.2 确认)

这是我的 Firebase 架构:

这是代码:

.factory('watchers', function(bunch-of-dependencies) {
  var unbindShifts = function() {};
  var inited = false;
  var shifts = {};

...中间有一些不相关的代码...

  function initShifts() {
     unbindShifts();
     shifts.object = firebaseConn.getShifts( false, from, to, $scope );

     $scope.shifts = shifts.object;
     shifts.object.$bindTo($scope, "shifts").then(function(unbind) {
        unbindShifts = unbind;
     });
  }

firebase 查询(在添加取消绑定/绑定之前运行良好,并且可能基于时间的查询也可能会导致问题):

  firebaseConn.getShifts = function(asArray, from, to, scope) {
     return cacheRequest(FBURL + "shifts", asArray, [from, to]);
  };

  function cacheRequest(url, asArray, limits) {
     var type = asArray ? "array" : "object";
     var startAt = limits ? limits[0] : undefined;
     var endAt = limits ? limits[1] : undefined;
     var retObj, FBRef;

     cached[url] = cached[url] || {};

     /* If there are limits-parameters we don't cache at all atm. Since those queries should be checked differently than static urls */
     if(!limits && cached[url][type]) {
        FBRef = cached[url][type];
     } else {
        FBRef = cached[url][type] = createFBRef(url, startAt, endAt);
     }

     if(asArray) {
        retObj = FBRef.$asArray();
     } else {
        retObj = FBRef.$asObject();
     }

     return retObj;
  }

  function createFBRef(resourceURL, startAt, endAt) {
     var modifiedObject = $firebase( createRef( resourceURL ).orderByKey().startAt(startAt).endAt(endAt) );

     return modifiedObject;
  }

  function createRef(resourceURL) {
     return new Firebase( resourceURL );
  }

现在我发现问题出在查询限制上。如果未定义 from 和 to 日期,则可以正常工作。但我需要能够限制数据量,因为加载多年的轮班数据,以显示一周的时间,不会很好:)。

实际问题是不显示和获取数据,一切正常,它与时间和重新绑定有关。

如果我对例如“20150115”-表。例如,我在那里添加了另一个“组”-child。当我取消绑定并重新绑定时,整个“20150115”表被删除,这仅适用于最新的更改。如果我将多个孩子添加到不同的日期,例如“20150113”、“20150114”、“20150115”和最新的变化是“20150115”然后我从firebase解绑+重新绑定一次,所有其他根路径将保持原样,但最新的变化是"20150115" 会删除整棵树。

我希望我说清楚,所以为了安全起见,我尝试以更简单的方式再次解释它。 - 通过应用程序更改为 1.“20150113”、2.“20150114”、3.“20150115”。 - 从 UI 更改时间线原因:取消绑定 + 重新绑定 - 作为副作用,整个“20150114”树被删除。

这个问题在某种程度上与使用 orderByKey().startAt(startAt).endAt(endAt) 和绑定的高级查询有关。

也可获取更多信息。通过 UI 添加的数据被添加到 firebase 数据库,但是当重新绑定发生时,数据会从数据库中删除。特别是在重新绑定时,如果我通过超时延迟重新绑定,解除绑定不会导致任何问题。

编辑:

我找到了实际问题的根源。在新的绑定到位并且一切似乎都井井有条之后,就会启动一个 angular watch 事件。该事件会尝试保存用户在重新绑定之前所做的最后一次更改。

因此,如果我有 12 月 (20141201 - 20141230) 的活动时间表并且我更改“20141225”-data。然后将时间线更改为 20150101 - 20150130,导致 unbind 和 rebind(或手动获取新数据)。在绑定完成并且一切似乎都井井有条之后,将发生一个事件,尝试将 20141225 数据保存到新时间线(20150101 - 20150130)或旧时间线,不确定是哪一个。这会导致 Firebase 实际删除整个 20141225 树,而不是保存数据。

【问题讨论】:

  • 嘿哈奇。听起来您正在开发一个很酷的应用程序,并且数据结构对于您描述的用例来说看起来很合理。但是我发现很难通过所有文本来理解您的问题。你能写一段最少的代码来重现你的问题吗? (stackoverflow.com/help/mcve)
  • @FrankvanPuffelen 嘿,弗兰克,当然。抱歉,如果我缺乏良好的解释技巧。这是我设法生成的一个 plunkr:plnkr.co/edit/Nk62dYfdiFvqkb9fT06F?p=preview。所以推“addNew”,看到添加的新条目,推“前进”,然后“后退”,由于某种原因,该条目已从 Firebase 中删除。
  • 当我采取这些步骤时,新数据仍保留在 Firebase 中。您可以通过new Firebase("https://your.firebaseio.com").once('value', function(s) { console.log(JSON.stringify(s.val())); }) 轻松测试。但是您的setDays 中缺少$scope.$apply()。我会写一个快速的答案和一些相关问题的指针。

标签: firebase angularfire


【解决方案1】:

新数据可以很好地进入您的 Firebase,您可以通过检查 Firebase 仪表板或在浏览器的开发控制台中运行类似这样的快速 sn-p 来查看:

new Firebase("https://firebaseurl").once('value', function(s) { console.log(s.val()); })

数据甚至会重新回到您的应用程序中。唯一的问题是 Angular 不知道新数据已经到达,所以它不会用新数据更新视图。

通常 AngularFire 的 $asObject$asArray 方法会在新数据从 Firebase 到达时通知 AngularJS。但由于您不断创建新查询,因此您必须自己处理。

有几种方法可以向 AngularJS 发出新数据的信号,我绝对不是哪一种最好的专家。但是,如果您将 $scope.$apply(); 添加到您的 setDays 函数中,它就会起作用:

function setDays(ref) {
  var FBRange = setFBRange(ref, from, to);
  var days;

  unbindDays();

  days = $firebase(FBRange).$asObject();
  $scope.days = days;

  days.$bindTo($scope, "days").then(function(unbind) {
      unbindDays = unbind;
      // As a result of the new binding entry gets mysteriously deleted from firebase
   });

   $scope.$apply(); // Tell AngularJS about the new data, so that it updates the view

  function setFBRange(ref, from, to) {
    return ref.orderByKey().startAt(""+from).endAt(from + to + "");
  }
}

使用此更改更新了 Plunkr(以及其他一些帮助调试):http://plnkr.co/edit/YZtkzUNtjQUCcw4xb2mj?p=preview

【讨论】:

  • 我试过 plnkr,谢谢!但不幸的是,它仍然无法正常工作:)。你错过了我遇到的实际问题。如果您会看到 firebase-dashboard,它会更容易显示,但是...我现在清空了 firebase 数据库...您可以通过尝试将 PERSISTENT 数据添加到数据库来看到问题。我的意思是:在不同的“日期”中推送 addNew 并尝试使数据在 forward:ing 和 backing:ing 之后留在数据库和应用程序中。由于某种原因它被删除了。虽然它是随机的。
  • 我现在正在尝试将完全相同的问题复制到 plunker。但到目前为止都失败了。我意识到原来 plunker 的问题可能相同,也可能不同。目前我有一个与我自己的应用程序略有不同的问题:plnkr.co/edit/MHR4AK?p=preview,但我最初的问题是持续存在的,这个问题更加随机。问题也可能与 angular 和 scope.apply 或其他无关。但不幸的是,我在消化/应用内部工作方面的专业知识也很有限。原来的问题表明与火力有关。
  • 即使使用目前的 plunker,它的工作方式也存在明显问题,我不确定问题出在哪里。我可以通过手动保存数据来解决这个问题,而不是 3 路数据绑定。但我仍然很想解决这个问题:/。
  • 是的,您确实缺少一些东西。实际上我一开始也错过了它:如果一个新项目会落入您现有的查询中,那么它将自动由 Firebase 同步到客户端,并由 AngularFire 同步到 Angular 视图。但在您的情况下,您正在创建一个新查询。新查询将获取新日期的数据。但是该数据不会同步到视图,因为您没有将 新查询 绑定到范围。这就是您必须手动执行此操作的原因。
  • AngularFire 在那个阶段还没有同步数据,所以它最终替换了现有数据。如果你想使用三向同步来更新数据,你应该确保数据是同步的。或者,您可以使用常规 Firebase API 对其进行更新:new Firebase("https://your.firebaseio.com").child(from-2).child('node').update({ insert: 1}); 刚才工作没有问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多