0

Ich brauche etwas Hilfe mit Versprechen, wenn möglich. Ich bin neu bei AngularJS und kann mir nicht vorstellen, wie ich mit dem Problem, das ich habe, umgehen kann. Im Grunde ist das Problem, dass ich zwei verschiedene Arrays habe, die asynchron initialisiert werden, während sie letztendlich beide Daten im selben Array speichern und dies in einer For-Schleife für mehrere Elemente tun. Der Bug, dem ich begegne, ist, dass während er die korrekte Menge an Elementen lädt, alle verschiedenen Benutzerdaten angezeigt werden, aber kein anderes Bild. Das angezeigte Bild ist für jeden Eintrag gleich. Am Ende des gesamten Codeabschnitt Sie diese finden:Abrufen von Firebase-Objekten in Schleife mit Versprechen

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); 
      } 
     }); 
    }); 

Ich bin ziemlich sicher, das ist, wo mein Problem ist. Es sucht nach neuen Benutzerdaten, ohne ein neues Bild zu verwenden. Ich bin mir jedoch nicht sicher, wie ich mit diesem Problem umgehen kann. Ich habe mehrere aufgeschobene Variablen und $ q.all untersucht, aber ich kann nicht genau sehen, wie ich das Problem angehen soll. Im Folgenden finden Sie den gesamten relevanten Code. Vielen Dank für jede Hilfe :)

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

die [latente Antipattern] Vermeiden Sie ersetzen sollte (http://stackoverflow.com/q/23803743/1048572)! – Bergi

+0

"*' if (newfriendsinfo.length == nefriends.length) '*" ist [wird nicht funktionieren] (http://stackoverflow.com/a/40032582/1048572). Warum nicht einfach '$ q.all' benutzen? – Bergi

Antwort

1

Das Problem ist auf jeden Fall in diesem Code.

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

Sie haben Versprechen verschachtelt und dies garantiert nicht, dass userPromise zuerst gelöst werden wird und picPromise wird zweite aufgelöst werden.

Sie sind zwei unabhängige asynchrone Aufrufe. Falls picPromise zuerst aufgelöst wird, wird der folgende Code niemals aufgerufen.

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

Abgesehen davon, auch wenn erste userPromise aufgelöst wird und dann picPromise Sie werden immer noch Probleme haben. Sie verwenden Variablen newfriendid und newfriendagreed in Versprechen, die außerhalb des Versprechens in Zyklus erstellt wird. Hier haben Sie ein Problem von Closures.

Hier ist, was passiert, wenn asyncUpdateFriendsInfo Funktion aufgerufen wird.

Wenn für Zyklus beendet ist alles Anfrage (aber Antworten sind noch nicht erhalten) gesendet wird und newfriendid und newfriendagreed Punkt newfriends ‚s letzte Rekord $id und agreed. Also in newfriendsinfo werden alle newfriendid gleich sein und zuletzt newfriendid sein.

Schauen Sie sich diese Frage für "Asynchronous Process inside a javascript for loop"

Wenn Tatsache, dass Sie diesen Code

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); 
     } 
    }); 
}); 

in so etwas wie dieses

(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

Vielen Dank! Das hat es getan und ich denke, dass ich jetzt viel besser verstehe, wie es gemacht wird :) Ich schätze die Hilfe! – Robin

+1

Willkommen. Ich denke, Sie müssen den Titel der Frage in etwas wie ändern. "Abrufen von Firebase-Objekten in einer Schleife mit Versprechen".Vielleicht ist das nicht der beste Titel, aber was Sie jetzt haben, ist völlig falsch. –

+0

Yeah du hast Recht, habe gerade :) – Robin

Verwandte Themen