Javascript 正在尝试将工厂中的ref.on()值返回给控制器

Javascript 正在尝试将工厂中的ref.on()值返回给控制器,javascript,angularjs,firebase,Javascript,Angularjs,Firebase,我正在尝试从工厂中的Firebase查询检索值到控制器,但没有成功。有人有主意吗 控制器: main.controller("mainCtrl", function($scope, totalusers){ $scope.city = "whatever"; $scope.total = totalusers.getusers($scope.city); }); 工厂(在这里我可以查询有多少用户指定了名称): 任何线索都很好,谢谢;) 对firebase值的访问是异步完成的,因此当将其

我正在尝试从工厂中的Firebase查询检索值到控制器,但没有成功。有人有主意吗

控制器:

main.controller("mainCtrl", function($scope, totalusers){
  $scope.city = "whatever";
  $scope.total = totalusers.getusers($scope.city);
});
工厂(在这里我可以查询有多少用户指定了名称):


任何线索都很好,谢谢;)

对firebase值的访问是异步完成的,因此当将其分配给
总计时,计数值仍然为0,然后立即返回。您可以使用
$q
服务创建承诺,并在firebase回调返回时解决它

app.factory("totalusers", function(FURL, $q){
  var gettotalusers = {};
  gettotalusers.getusers = function(city){
    var tusers = new Firebase(FURL + "/Users/" + city);
    var count = 0;
    var deferred = $q.defer();

    tusers.on("value", function(snapshot){
      snapshot.forEach(function(child) {
        if(child.val().Name != undefined){
          count++;
        }
      });
      deferred.resolve(count);
    });

    return deferred.promise;
  }
  return gettotalusers;
});
然后在控制器中,不能直接分配结果。您需要在承诺处理程序方法中这样做:

main.controller("mainCtrl", function($scope, totalusers){
  $scope.city = "whatever";
  totalusers.getusers($scope.city).then(
    function(total) {
      $scope.total = total;
    },
    function(err) {
      // handle error
    }
  );
});
有关更多详细信息,请参阅$q文档并阅读有关承诺的概念。

您还可以尝试使用filter and reduce以更实用的方式编写计数:

var total = snapshot
  .filter(function(item) { return child.val().Name !== undefined })
  .reduce(function(acc, curr) {
    return acc + curr;
  }
);

访问firebase值是异步完成的,因此当将其分配给
总计时,计数值仍然为0,然后立即返回。您可以使用
$q
服务创建承诺,并在firebase回调返回时解决它

app.factory("totalusers", function(FURL, $q){
  var gettotalusers = {};
  gettotalusers.getusers = function(city){
    var tusers = new Firebase(FURL + "/Users/" + city);
    var count = 0;
    var deferred = $q.defer();

    tusers.on("value", function(snapshot){
      snapshot.forEach(function(child) {
        if(child.val().Name != undefined){
          count++;
        }
      });
      deferred.resolve(count);
    });

    return deferred.promise;
  }
  return gettotalusers;
});
然后在控制器中,不能直接分配结果。您需要在承诺处理程序方法中这样做:

main.controller("mainCtrl", function($scope, totalusers){
  $scope.city = "whatever";
  totalusers.getusers($scope.city).then(
    function(total) {
      $scope.total = total;
    },
    function(err) {
      // handle error
    }
  );
});
有关更多详细信息,请参阅$q文档并阅读有关承诺的概念。

您还可以尝试使用filter and reduce以更实用的方式编写计数:

var total = snapshot
  .filter(function(item) { return child.val().Name !== undefined })
  .reduce(function(acc, curr) {
    return acc + curr;
  }
);
在这种情况下使用
ref.on()
是一个坏主意,因为即使在函数完成后,它仍将继续同步该节点。您应该调用
ref.off()
,或者更简单地说,使用
ref.once()
。如果您使用的是最新版本的Firebase,这将返回一个承诺,这意味着您不需要
$q

app.factory("totalusers", function(FURL) {
    var gettotalusers = {};

    gettotalusers.getusers = function(city) {
        var tusers = new Firebase(FURL + "/Users/" + city);

        return tusers.orderByChild("Name")
                     .startAt(false)
                     .once("value")
                     .then(function(snapshot) {
            return snapshot.numChildren();
        });
    };

    return gettotalusers;
});
在这种情况下使用
ref.on()
是一个坏主意,因为即使在函数完成后,它仍将继续同步该节点。您应该调用
ref.off()
,或者更简单地说,使用
ref.once()
。如果您使用的是最新版本的Firebase,这将返回一个承诺,这意味着您不需要
$q

app.factory("totalusers", function(FURL) {
    var gettotalusers = {};

    gettotalusers.getusers = function(city) {
        var tusers = new Firebase(FURL + "/Users/" + city);

        return tusers.orderByChild("Name")
                     .startAt(false)
                     .once("value")
                     .then(function(snapshot) {
            return snapshot.numChildren();
        });
    };

    return gettotalusers;
});

谢谢你的快速回复。它运行得非常好。我不知道过滤器和减压器,但我要看一下并检查一下。如果你有一个例子,这将是很酷的。无论如何,我对FialBaseAPI没有任何经验,所以请考虑“ANNID MunSURR”的解释,并使用FielaseAPI返回的承诺。如果您想了解更多关于数组函数的信息,我认为mozilla文档是一个很好的资源:感谢您的快速回复。它运行得非常好。我不知道过滤器和减压器,但我要看一下并检查一下。如果你有一个例子,这将是很酷的。无论如何,我对FialBaseAPI没有任何经验,所以请考虑“ANNID MunSURR”的解释,并使用FielaseAPI返回的承诺。如果你想了解更多关于数组函数的信息,我认为mozilla文档是一个很好的资源:您好@AnidMonsur,您说得对,我注意到ref.on()将继续关注,所以我改为ref.once()。虽然上面的代码并不完全是我想要做的,因为我需要的是检查有多少保存到firebase中的“名称”的用户可用,并对他们进行计数,但您所做的是对所有用户进行计数。无论如何,谢谢。啊,好的。更新了我对该场景的回答。从
false开始
由于Firebase的订单非常感谢您的帮助,我尝试了您的代码,它运行得非常好,我只需要更新到最新的Firebase版本(2.4.1),因为我对.once()有一个错误,它只有一个参数,无论如何,现在它工作得很好,非常感谢。我只是注意到它仍然在计算所有用户,因为我尝试测试它的名称:“在firebase中的一个用户中,但它仍然计算所有用户,我刷新页面以重新加载代码,但它仍然是。
是一个空字符串。您的原始代码也会考虑到这一点,因为它不是
未定义的
。您好@AnidMonsur,您是对的,我注意到ref.on()将继续监视,所以我改为ref.once()。虽然上面的代码并不完全是我想要做的,因为我需要的是检查有多少保存到firebase中的“名称”的用户可用,并对他们进行计数,但您所做的是对所有用户进行计数。无论如何,谢谢。啊,好的。更新了我对该场景的回答。从
false开始
由于Firebase的订单非常感谢您的帮助,我尝试了您的代码,它运行得非常好,我只需要更新到最新的Firebase版本(2.4.1),因为我对.once()有一个错误,它只有一个参数,无论如何,现在它工作得很好,非常感谢。我只是注意到它仍然在计算所有用户,因为我尝试测试它的名称:“在firebase中的一个用户中,但它仍然计算所有用户,我刷新页面以重新加载代码,但它仍然是。
是一个空字符串。您的原始代码也会计算在内,因为它不是未定义的。