1

저는 firebase의 데이터를 가져 와서 html로 표시하는 함수를 실행하는 버튼이 있습니다 (저는 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 - Anytime! 이 방법으로 문제가 해결되면 승인 된 답변으로 작성하십시오. Fyi ... $ scope.apply와 $ timeout에 대한 자세한 내용은 여기를 참조하십시오. http://stackoverflow.com/questions/23070822/angular-scope-apply-vs-timeout-as-a-safe-apply – grumpyhoser

1

약속의 목적은 비동기 방법을 관리하는 것입니다, 그래서 정말 문제를 이해하지 않는 ...

또한 일반적으로 displayChat 내부의 코드가 실행되어야 만 콜백 후 실행해야합니다. 필요한 비동기 메서드가 완료되면 콜백을 실행할 수 있도록 약속을 반환해야합니다.

1

범위를 변경하여 수행하는 경우 AngularJS 프레임 워크 외부의 이벤트 인 경우 프레임 워크는 DOM을 업데이트하는 다이제스트주기를 시작하기 위해 $ 적용을해야합니다.

$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를 사용하여 오류 경우에 약속을 거부해야합니다.

관련 문제