【问题标题】:Firebase, AngularJS and GeoFire - wait for response from factoryFirebase、AngularJS 和 GeoFire - 等待工厂的响应
【发布时间】:2015-01-09 22:43:17
【问题描述】:

我开始学习很多与混合应用编码相关的知识。我决定继续使用基于 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 不知道这个变化?

再次感谢!

【问题讨论】:

  • 要详细了解为什么需要调用 $apply,请参阅jimhoskins.com/2012/12/17/angularjs-and-apply.html
  • 我刚刚发布了那个链接 ^^ 问题是为什么 Angular 不知道这个变化,因为它被包装在 Angular 事件类型中?
  • 没有包裹在 Angular 事件中。您传递给then 的回调可以并且将在任何时候触发。所以 Angular 对此一无所知,除非你告诉它。不过,不要相信我或任何人的话:只需在 $scope.data.myLoc 行上设置一个断点并检查堆栈跟踪,它很可能与您预期的不同。
  • 这很有趣,非常感谢(再次)!

标签: javascript angularjs firebase geofire


【解决方案1】:

您被 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") 时,它会向服务器发出请求。该请求可能需要一些时间,我们不希望浏览器被阻止。因此,我们不是等待请求完成,而是传入一个函数,以便在服务器响应请求的数据时调用。由于可能会出错,因此我们还传入了一个函数以在发生错误时调用。

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

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

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

【讨论】:

  • 您好弗兰克,非常感谢您的回答!首先,我应该写下我确实理解了这个理论:我遵循了 Thinkster.io 教程并观看了 Egghead.io 视频。所以你说的一切对我来说都很有道理。我也非常了解回调函数。无论如何,祝贺您的详细程度:) 现在,我可能明白这一点,但仍然不知道如何处理我的控制器以及如何等待答案。我确实使用 AngularFire,所以如果它包含一个答案,那对我来说很好!基本上我需要了解控制器如何等待工厂的答复......
  • David 在他早期的一个视频中解释了 Firebase 的异步特性。
  • 好的,我去看看,反正我已经创建了免费试用帐户:)谢谢你的帮助。
  • 如果您对如何使用 AngularFire 完成我的目标而不在控制器中调用 GeoFire 有任何建议,我很乐意接受!
  • 视频也在 youtube 上,不需要在那里付款。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-04
  • 2016-05-26
  • 1970-01-01
  • 1970-01-01
  • 2015-11-10
  • 1970-01-01
相关资源
最近更新 更多