1

我开始学习很多与混合应用程序编码相关的东西。我决定继续使用基于 AngularJS 的 Ionic 框架(这让我有机会学习它),并使用 Firebase 作为我的后端解决方案。

我想在我的应用程序中设置一个地图,以便找到用户和他周围的一些兴趣点。我发现 GeoFire 存在,所以我开始使用它。

我的问题:我无法显示保存到 Firebase 中的用户位置。我使用 GeoFire 查询它,并获得响应(console.log 它),但它不会更新范围变量。

这是JS代码:

myApp.factory("MyLoc", function(){
    var firebaseRef = new Firebase("https://myfirebase.firebaseio.com/geofire/");
    var geoFire = new GeoFire(firebaseRef);

    /*    geoFire.set("user_loc", [37.785326, -122.405696]).then(function() {
     console.log("Provided key has been added to GeoFire");
     }, function(error) {
     console.log("Error: " + error);
     });*/

     return geoFire.get("user_loc").then(function(location) {
        if (location === null) {
            console.log("Provided key is not in GeoFire");
            return 0;
        }
        else {
            console.log("Provided key has a location of " + location);
            return location;
        }
    }, function(error) {
        console.log("Error: " + error);
        return 0;
    });
})

myApp.controller("firstCtrl", function($scope, MyLoc) {
    $scope.data = {};

    $scope.data.myLoc = MyLoc;
});

HTML 只是显示它:

{{data.myLoc}}

由于我是 Angular N00b,我想我遗漏了一些明显的东西。我想我应该使用承诺或类似的东西,只是不知道怎么做!有人能帮助我吗 ?:)

非常感谢兄弟们!

[更新]

好的,这是第一个问题的答案!

MyLoc.then(function(data){
  $scope.data.myLoc = data;

  $scope.$apply();
});

但是我不得不使用

$scope.$apply();

为了让 HTML 显示它,显然它不会立即更新。你知道为什么吗?我知道 Angular 必须被通知更改才能显示,这里很好地解释了:http: //jimhoskins.com/2012/12/17/angularjs-and-apply.html

我不明白,为什么会出现这种情况?为什么 Angular 不知道这个变化?

再次感谢 !

4

1 回答 1

4

Firebase 的 API 是异步的,这让您感到困惑。您不能以您尝试的方式从异步调用返回值:

这是您的代码的相关片段:

myApp.factory("MyLoc", function(){
    var firebaseRef = new Firebase("https://myfirebase.firebaseio.com/geofire/");
    var geoFire = new GeoFire(firebaseRef);

     return geoFire.get("user_loc").then(function(location) {
        if (location === null) {
            console.log("Provided key is not in GeoFire");
            return 0;
        }
        else {
            console.log("Provided key has a location of " + location);
            return location;
        }
    }, function(error) {
        console.log("Error: " + error);
        return 0;
    });
})

注意你传入的那些函数then?这些被称为回调函数,是 Firebase(以及一般现代网络)异步操作的关键。如果将这些回调提取到常规的、全局的、命名的函数中,则更容易看出为什么您的构造不起作用:

myApp.factory("MyLoc", function(){
    var firebaseRef = new Firebase("https://myfirebase.firebaseio.com/geofire/");
    var geoFire = new GeoFire(firebaseRef);

     return geoFire.get("user_loc").then(onGeoFireResult, onGeoFireError);
})

function onGeoFireResult(location) {
    if (location === null) {
        console.log("Provided key is not in GeoFire");
        return 0;
    }
    else {
        console.log("Provided key has a location of " + location);
        return location;
    }
}

function onGeoFireError(error) {
    console.log("Error: " + error);
    return 0;
}

当您调用geoFire.get("user_loc")它时,它会向服务器发出请求。该请求可能需要一些时间,我们不希望浏览器被阻止。因此,我们不是等待请求完成,而是传入一个函数,以便在服务器响应请求的数据时调用。由于事情可能会出错,我们还传入一个函数以在发生错误时调用。

因此,重要的是要意识到onGeoFireResultand的onGeoFireError运行时间与调用 的时间不同geoFire.get("user_loc")。所以你不能从封装函数返回它们的结果。相反,您必须处理承诺的概念:一种结构,在某些时候将拥有您请求的数据。

如果您想在不使用 AngularFire 的情况下继续使用 Firebase 和 Angular,我强烈建议您观看此视频教程:https ://www.youtube.com/watch?v=3YVlcFyxBr4 。花一个小时左右的时间可以为你节省几十个问题。

或者设置两个断点:一个在行上onGeoFireResult,一个在行后geoFire.get("user_loc"),看看哪个断点首先触发。

于 2014-11-13T14:28:48.757 回答