使用 promises 循环获取 firebase 对象
Fetching firebase objects in loop with promises
如果可能的话,我需要一些关于承诺的帮助。我是 AngularJS 的新手,不知道如何处理我遇到的问题。基本上,问题是我有两个异步初始化的不同数组,同时最终将两个数据存储在同一个数组中,并在多个项目的 for 循环中执行此操作。我遇到的错误是,虽然它加载了正确数量的项目,但它显示了所有不同的用户数据,但没有显示不同的图片。每个条目显示的图片相同。在整个代码部分的末尾,您会发现:
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;
}
问题肯定出在这段代码中。
userPromise.then(function(user){
picPromise.then(function(url){
您有嵌套的承诺,这并不能保证 userPromise
会首先得到解决,picPromise
会得到第二个解决。
它们是两个独立的异步调用。如果 picPromise
首先被解析,则永远不会调用以下代码。
newfriendsinfo.push({
id: newfriendid,
name: user.val().name,
email: user.val().email,
agreed: newfriendagreed,
profilepicture: url
});
除此之外,即使先 userPromise
解决然后 picPromise
你仍然会有问题。
您在 promise 中使用变量 newfriendid
和 newfriendagreed
,这是在 promise in cycle 之外创建的。这里有 Closures.
的问题
调用 asyncUpdateFriendsInfo
函数时会发生什么。
当 for 循环完成时,将发送所有请求(但尚未收到响应)并且 newfriendid
和 newfriendagreed
指向 newfriends
的最后一条记录的 $id
和 agreed
。所以在 newfriendsinfo
中,所有 newfriendid
都是一样的,并且最后 newfriendid
.
查看“Asynchronous Process inside a javascript for loop”这个问题“=32=]
如果确实如此,您应该替换此代码
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);
}
});
});
变成这样
(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);
如果可能的话,我需要一些关于承诺的帮助。我是 AngularJS 的新手,不知道如何处理我遇到的问题。基本上,问题是我有两个异步初始化的不同数组,同时最终将两个数据存储在同一个数组中,并在多个项目的 for 循环中执行此操作。我遇到的错误是,虽然它加载了正确数量的项目,但它显示了所有不同的用户数据,但没有显示不同的图片。每个条目显示的图片相同。在整个代码部分的末尾,您会发现:
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;
}
问题肯定出在这段代码中。
userPromise.then(function(user){
picPromise.then(function(url){
您有嵌套的承诺,这并不能保证 userPromise
会首先得到解决,picPromise
会得到第二个解决。
它们是两个独立的异步调用。如果 picPromise
首先被解析,则永远不会调用以下代码。
newfriendsinfo.push({
id: newfriendid,
name: user.val().name,
email: user.val().email,
agreed: newfriendagreed,
profilepicture: url
});
除此之外,即使先 userPromise
解决然后 picPromise
你仍然会有问题。
您在 promise 中使用变量 newfriendid
和 newfriendagreed
,这是在 promise in cycle 之外创建的。这里有 Closures.
调用 asyncUpdateFriendsInfo
函数时会发生什么。
当 for 循环完成时,将发送所有请求(但尚未收到响应)并且 newfriendid
和 newfriendagreed
指向 newfriends
的最后一条记录的 $id
和 agreed
。所以在 newfriendsinfo
中,所有 newfriendid
都是一样的,并且最后 newfriendid
.
查看“Asynchronous Process inside a javascript for loop”这个问题“=32=]
如果确实如此,您应该替换此代码
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);
}
});
});
变成这样
(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);