0

가능한 경우 약속에 대한 도움이 필요합니다. 나는 AngularJS에 처음 왔고 내가 겪고있는 문제를 어떻게 다룰 지 알 수 없습니다. 기본적으로 두 개의 서로 다른 배열이 비동기식으로 초기화되는 반면 궁극적으로 두 배열을 같은 배열에 저장하고 for 루프에서 여러 항목을 저장합니다. 내가 만나는 버그는 정확한 양의 항목을로드하는 동안 다른 사용자 데이터를 모두 표시하지만 다른 그림은 표시하지 않는다는 것입니다. 표시되는 그림은 각 항목에 대해 동일합니다. 전체 코드 섹션의 끝 부분에서 다음을 찾으십시오.약속을 지닌 루프에서 firebase 객체 가져 오기

userPromise.then(function(user){ 
     picPromise.then(function(url){ 
      newfriendsinfo.push({ 
       id: newfriendid, 
       name: user.val().name, 
       email: user.val().email, 
       agreed: newfriendagreed, 
       profilepicture: url 
      }); 
     }).then(function(){ 
      if (newfriendsinfo.length == newfriends.length){ 
       deferred.resolve(newfriendsinfo); 
      } 
     }); 
    }); 

여기가 내 문제가되는 곳입니다. 새 사진을 사용하지 않는 동안 새 사용자 데이터를 찾습니다. 그러나이 문제를 어떻게 처리 할 수 ​​있는지 잘 모르겠습니다. 여러 개의 지연 변수와 $ q.all을 살펴 봤지만 문제를 어떻게 해결할 수 있는지 알 수 없습니다. 아래에서 전체 관련 코드를 찾을 수 있습니다. 감사합니다 도움 :

var friendsRef = firebase.database().ref('friendships/' + firebase.auth().currentUser.uid); 

$scope.friends = $firebaseArray(friendsRef); 

$scope.friendsinfo = []; 

$scope.$watch('friends', function() { 
    var newfriends = $scope.friends; 

    asyncUpdateFriendsInfo(newfriends).then(function(newlist){ 
     $scope.friendsinfo = newlist; 
    }); 
}, true); 

function fetchPicture(ref){ 
    return ref.getDownloadURL().then(function(url) { 
     return url; 
    }).catch(function(error) { 
     alert("error"); 
    }); 
} 

function fetchUserInfo(ref){ 
    return ref.once('value', function(snapshot){ 

    }).then(function(snapshot){ 
     return snapshot; 
    }); 
} 

function asyncUpdateFriendsInfo(newfriends){ 
var deferred = $q.defer(); 
var newfriendsinfo = []; 

for(var i = 0; i < newfriends.length; i++){ 
    var ref = firebase.database().ref('users/' + newfriends[i].$id); 
    var profilePicRef = firebase.storage().ref("profilepictures/" + newfriends[i].$id + "/profilepicture"); 
    var userPromise = fetchUserInfo(ref); 
    var picPromise = fetchPicture(profilePicRef); 

    var newfriendid = newfriends[i].$id; 
    var newfriendagreed = newfriends[i].agreed; 

    userPromise.then(function(user){ 
     picPromise.then(function(url){ 
      newfriendsinfo.push({ 
       id: newfriendid, 
       name: user.val().name, 
       email: user.val().email, 
       agreed: newfriendagreed, 
       profilepicture: url 
      }); 
     }).then(function(){ 
      if (newfriendsinfo.length == newfriends.length){ 
       deferred.resolve(newfriendsinfo); 
      } 
     }); 
    }); 
} 

return deferred.promise; 

}

+2

같은이 코드

userPromise.then(function(user){ picPromise.then(function(url){ newfriendsinfo.push({ id: newfriendid, name: user.val().name, email: user.val().email, agreed: newfriendagreed, profilepicture: url }); }).then(function(){ if (newfriendsinfo.length == newfriends.length){ deferred.resolve(newfriendsinfo); } }); }); 

를 교체해야하는 경우 (HTTP ://stackoverflow.com/q/23803743/1048572)! – Bergi

+0

"*'if (newfriendsinfo.length == newfriends.length)'* '는 [작동하지 않을 것입니다] (http://stackoverflow.com/a/40032582/1048572). 왜 단순히'$ q.all '을 사용하지 않는가? – Bergi

답변

1

문제는이 코드에 확실히에 대한 많은.

userPromise.then(function(user){ 
    picPromise.then(function(url){ 

당신은 약속을 중첩하고이 userPromise 먼저 해결 될 것이라는 점을 보장하지 않으며, picPromise 두 번째 해결 될 것입니다.

두 개의 독립적 인 비동기 호출입니다. picPromise이 먼저 해결 된 경우 다음 코드는 절대로 호출되지 않습니다. userPromise 첫째가 해결 된 다음 문제가 계속됩니다 picPromise 경우에도 그 외에

newfriendsinfo.push({ 
    id: newfriendid, 
    name: user.val().name, 
    email: user.val().email, 
    agreed: newfriendagreed, 
    profilepicture: url 
}); 

. 약속에서 벗어난 약속으로 만들어진 변수 newfriendidnewfriendagreed을 사용 중입니다. 여기에 Closures의 문제가 있습니다.

여기에 asyncUpdateFriendsInfo 함수가 호출되면 어떻게됩니까?

주기에 대한 모든 요청이 전송됩니다 완료 (그러나 응답이 아직 접수되지 않음) 및 newfriends의 마지막 레코드의 $idagreed-newfriendidnewfriendagreed 포인트합니다. 따라서 newfriendsinfo에서 모두 newfriendid은 동일하며 마지막으로 newfriendid이됩니다.

체크 아웃 "Asynchronous Process inside a javascript for loop"

이 질문을 사실 당신이 [지연 안티 패턴]을 피하십시오이

(function(newfriendid){ 
    var finalUser, 
     finalUrl; 

    userPromise.then(function(user){ 
     finalUser = user; 
     checkIfBothLoaded(); 
    }); 

    picPromise.then(function(url){ 
     finalUrl = url; 
     checkIfBothLoaded(); 
    }); 

    function checkIfBothLoaded(){ 
     if (finalUser && finalUrl){ 
      newfriendsinfo.push({ 
       id: newfriendid, 
       name: finalUser.val().name, 
       email: finalUser.val().email, 
       agreed: newfriendagreed, 
       profilepicture: finalUrl 
      }); 
     } 

     if (newfriendsinfo.length == newfriends.length){ 
      deferred.resolve(newfriendsinfo); 
     } 
    } 

})(newfriendid, newfriendagreed); 
+0

고마워요! 그것은 그랬고 나는 그것이 어떻게 끝났는 지에 대해 훨씬 더 잘 이해하고 있다고 생각합니다. 저는 도움에 감사드립니다! – Robin

+1

환영합니다. 나는 당신이 질문의 제목을 비슷한 것으로 바꿀 필요가 있다고 생각합니다. "약속을 가진 루프에서 Firebase 객체를 가져 오는 중".어쩌면 이것이 최고의 타이틀은 아니지만 지금 당신이 가진 것은 완전히 틀린 것입니다. –

+0

그래, 네 말이 맞아. :) – Robin

관련 문제