1

ハイブリッド アプリのコーディングに関連する多くのことを学び始めています。私は、AngularJS に基づいた Ionic フレームワークを使用することに決めました (これは私にそれを学ぶ機会を与えてくれます)、そして Firebase をバックエンド ソリューションとして使用することにしました。

アプリでマップをセットアップしたいので、ユーザーとその周辺のいくつかの興味のあるポイントを見つけます。GeoFire の存在を知ったので、それを使い始めました。

私の問題: Firebase に保存されているユーザーの場所を表示できません。GeoFire を使用してクエリを実行し、応答 (console.log it) を取得しますが、スコープ変数は更新されません。

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 (および一般的な最新の Web) の非同期操作の鍵となります。これらのコールバックを通常のグローバルな名前付き関数に抽出すると、構成が機能しない理由を簡単に確認できます。

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")と、サーバーへのリクエストが実行されます。そのリクエストには時間がかかる場合があり、ブラウザがブロックされることは望ましくありません。そのため、リクエストが完了するのを待つ代わりに、サーバーがリクエストされたデータで応答したときに呼び出される関数を渡します。問題が発生する可能性があるため、エラーが発生した場合に呼び出される関数も渡します。

したがって、 と は、 を呼び出すときとは異なるときに実行されることonGeoFireResultに注意してください。したがって、カプセル化関数から結果を返すことはできません。代わりに、Promise の概念に対処する必要があります。つまり、ある時点で要求したデータを持つ構造体です。onGeoFireErrorgeoFire.get("user_loc")

AngularFire を使用せずに Firebase と Angular を引き続き使用する場合は、次のビデオ チュートリアルに従うことを強くお勧めします: https://www.youtube.com/watch?v=3YVlcFyxBr4。ここで 1 時間ほど費やすと、ここで何十もの質問を省くことができます。

または、2 つのブレークポイントを設定します。1 つはオンにonGeoFireResult、もう 1 つは後の行に配置しgeoFire.get("user_loc")、どちらのブレークポイントが最初にトリガーされるかを確認します。

于 2014-11-13T14:28:48.757 に答える