1

私はhtmlのfirebaseからデータを取得して表示する機能を実行するボタンを持っています(私はangularJS、ionic、firebaseを使用しています)。は正常に機能していることを約束しています

問題は次のとおりです。私の後に.then(function(){})をインクルードしないと、プロミスは非同期で実行されます。つまり、データが表示されるようにもう一度ボタンをクリックする必要があります。 html。

私は約束の後に(firebaseからデータを取得する)スコープにデータを入れたいと思っていますが、何らかの理由で、後に.then関数を置くと動作するだけです。

しかし、データはコンソールでは正常に表示されますが、htmlでは表示されません(つまり、関数がスコープに接続されていないと思われます)。

$scope.displayChat = function() { 
    var userId = firebase.auth().currentUser.uid; // Get ID 
    var deferred = $q.defer() 

    var db = firebase.database(); 
    var ref = db.ref("12346787"); 

    ref.on("value", function(snapshot) { 
      console.log(snapshot.val()); 
      $scope.chatArray = snapshot.val(); 
      deferred.resolve() 

     }, function (errorObject) { 
      console.log("The read failed: " + errorObject.code); 
     }) 

    return deferred.promise.then(function(){ 
     // Removing this empty .then(function(){}) function 
     // will result in asynchronousity. 
     // just "return deferred.promise;" doesn't work. 
    }) 
} 

どれソリューション:ここ

は、コードの一部はありますか?私は約束の経験はあまりありませんが、関連するものは何も見つかりませんでした。乾杯。

+1

なぜ約束が必要ですか?あなたは何かを解決するメモです。 ** deferred.resolve()** - >は値を解決しません。 – Hosar

答えて

0

プロミスは、約束が満たされるまで、すなわちデータベースから結果を受け取るまで、ロジックの実行を延期するために使用されます。あなたのケースでは、すでにコンソール表示と$ scope変数の設定をref.onの範囲で延期しています。約束コードは冗長です。

あなたの結果がコンソールに表示されたということは、あなたが結果を受け取ったことを証明します。スコープ内のデータを更新すると、ダイジェストサイクルが発生するまで表示されません。ほとんどの場合、Angularはダイジェストサイクルをいつ実行する必要があるかを自動的に把握できます。次のようにそうでないとき、あなたはタイムアウトであなたのスコープ関連のロジックをラップすることにより、それを強制することができ、これらの回では、その場合には、あなたのコードがなります

$scope.displayChat = function() { 
var userId = firebase.auth().currentUser.uid; // Get ID 

var db = firebase.database(); 
var ref = db.ref("12346787"); 

ref.on("value", function(snapshot) { 
     console.log(snapshot.val()); 
     $timeout(function() { 
      $scope.chatArray = snapshot.val(); 
     }); 

    }, function (errorObject) { 
     console.log("The read failed: " + errorObject.code); 
    }) 

}

約束のご利用を.thenメソッドがダイジェストサイクルをトリガしたばかりです。約束自体は本当に何もしていなかった。

は、あなたの意図は、それが利用可能になったときに、呼び出し元に戻すスナップショットを渡すようにした場合は約束が場に出たとき、それはだ、と次のように行われることになります。

$scope.displayChat = function() { 
    var userId = firebase.auth().currentUser.uid; // Get ID 
    var deferred = $q.defer() 

    var db = firebase.database(); 
    var ref = db.ref("12346787"); 

    ref.on("value", function(snapshot) { 
      deferred.resolve(snapshot) 

     }, function (errorObject) { 
      console.log("The read failed: " + errorObject.code); 
     }) 

    return deferred.promise; 
}; 

$scope.callDisplayChat = function() { 
    $scope.displayChat().then(function (result) { 
     $scope.chatArray = result.val(); 
    }); 
}; 
+0

私はそれを得る、ありがとう!私の友人はこれを設定して、なぜこのことが起こったのか知らなかったので、私はここでそれに尋ねました。私は$ scope.digest()と$ scope.apply()について知っている/聞いたことがありますが、実際にどのように働いているのかは分かりませんでしたので、おかげさまでD – Pokfin

+0

@Pokfin - いつでも!これで問題が解決した場合は、それを受け入れられた回答としてください。 Fyi ... $ scope.apply vs $ timeoutの詳細はこちら - http://stackoverflow.com/questions/23070822/angular-scope-apply-vs-timeout-as-a-safe-apply – grumpyhoser

1

約束の目的は、非同期メソッドを管理することですので、私は実際には問題を理解していない...

はまた、通常displayChat内のコードが実行されなければならない、唯一のコールバックが後に実行する必要があります。必要な非同期メソッドが完了したら、コールバックを実行できるようにする必要があります。

1

範囲の変更がで行われている場合AngularJSフレームワークの外部のイベントの場合、フレームワークはDOMを更新するダイジェストサイクルを開始するために$ applyを実行する必要があります。

$qサービス約束の.then方法は、自動的に必要なダイジェストサイクルを開始します。この場合、displayChat関数によって返された約束は破棄され、ダイジェストサイクルは開始されません。ボタンを続けてクリックすると、ダイジェストサイクルが開始されます。

将来、誰かがdisplayChat関数によって返された約束から連鎖したいと思うかもしれません。適切な約束を返し、スコープの変更を.thenメソッドに移すことで、関数の汎用性を高めることをお勧めします。また

$scope.displayChat = function() { 
    var userId = firebase.auth().currentUser.uid; // Get ID 
    var deferred = $q.defer() 

    var db = firebase.database(); 
    var ref = db.ref("12346787"); 

    //ref.on("value", function(snapshot) { 
    //USE once 
    ref.once("value", function(snapshot) { 
      console.log(snapshot.val()); 
      //$scope.chatArray = snapshot.val(); 
      deferred.resolve(snapshot.val()); 

     }, function (errorObject) { 
      console.log("The read failed: " + errorObject.code); 
      //ADD rejection case 
      deferred.reject(errorObject); 
     }) 

    return deferred.promise.then(function(chatArray){ 
     //Move scope changes here 
     $scope.chatArray = chatArray; 
     //RETURN to chain data 
     return chatArray; 

     // Removing this empty .then(function(){}) function 
     // will result in asynchronousity. 
     // just "return deferred.promise;" doesn't work. 
    }) 
} 

、メモリリークを避ける代わりにref.onref.onceを使用すると、エラーケースでの約束を拒否するようにしてくださいします。

関連する問題