我正在创建一个博客网站,并且正在编写按顺序执行以下操作的代码:
1。存储用户上传的多张照片
2。下载他们的网址
3。将它们保存到实时数据库中。
我写了下面的函数来做#1和#2。基本上,这个想法是将所有网址存储到一个数组中,在本例中为“ urlarray”。
function url_array_get(){
return new Promise(function(resolve,reject){
let filez=review_photo.files;
let urlarray=[];
let user=firebase.auth().currentUser;
let files=Array.from(filez);
files.forEach(function(file) {
let storageRef=firebase.storage().ref('data/'+user.uid+'/posts/'+file.name);
storageRef.put(file).then(function(snapshot){
snapshot.ref.getDownloadURL().then(function(url) {
urlarray.push(url);
})
})
});
if (!urlarray){
reject("oops");
}
else {
resolve(urlarray);
}
});
}
这是上载功能代码的一部分,该功能会将所有相关数据上载到数据库,包括上面函数中的promise返回的URL数组。 (为了使情况简洁,我省略了其余代码)
let userpostRef=firebase.database().ref('posts/');
let newpostRef=userpostRef.push();
newpostRef.set({
userid: user.uid,
post_target: rtarget,
post_content:rtext,
time: firebase.database.ServerValue.TIMESTAMP
}).then(function(){
url_array_get().then(function(result){
newpostRef.once('value', function(snapshot) {
newpostRef.update({
postnum:snapshot.key,
photolink:result
})
})})}).
then(function(){
alert("Upload successful!");
window.location.href='/'+username;
})
.catch(function(error){
alert("Error!");
});
}
这是问题所在:代码会将除“ photolink”(应为URL的数组)之外的所有内容写入数据库。
这是我在进行调试时发现的:
-照片存储没有问题。
为每个文件下载-urls,并按预期在执行代码中成功返回urlarray。
可能出了什么问题?我在这里迷路了。任何建议都将非常受欢迎。
非常感谢!
答案 0 :(得分:1)
每次调用storageRef.put(...)
都会启动一个异步操作。现在,您的``不等待这些异步操作完成,而是在填充URLS之前返回URL列表。
最简单的方法是在代码中添加一些简单的日志记录:
function url_array_get(){
return new Promise(function(resolve,reject){
let filez=review_photo.files;
let urlarray=[];
let user=firebase.auth().currentUser;
let files=Array.from(filez);
files.forEach(function(file) {
console.log("Starting to put file...");
let storageRef=firebase.storage().ref('data/'+user.uid+'/posts/'+file.name);
storageRef.put(file).then(function(snapshot){
console.log("Upload done, getting download URL...");
snapshot.ref.getDownloadURL().then(function(url) {
console.log("Download URL gotten, adding to array...");
urlarray.push(url);
})
})
});
if (!urlarray){
reject("oops");
}
else {
console.log("Resolving with "+urlarray.length+" download URLs");
resolve(urlarray);
}
});
}
运行此代码时,输出将如下所示:
开始放置文件...
开始放置文件...
开始放置文件...
使用0个下载URL解析
上传完成,获取下载URL ...
获得下载URL,并将其添加到数组中...
上传完成,获取下载URL ...
获得下载URL,并将其添加到数组中...
上传完成,获取下载URL ...
获得下载URL,并将其添加到数组中...
这当然不是您想要的顺序,因为您要在向数组添加任何下载URL之前甚至在任何上传完成之前返回数组。
解决方案是(一如往常涉及异步操作)要等到所有操作完成后才能解析/返回。您可以使用Promise.all()
最简单地执行以下操作:
function url_array_get(){
let promises = [];
let filez=review_photo.files;
let user=firebase.auth().currentUser;
let files=Array.from(filez);
files.forEach(function(file) {
let storageRef=firebase.storage().ref('data/'+user.uid+'/posts/'+file.name);
promises.push(
storageRef.put(file).then(function(snapshot){
return snapshot.ref.getDownloadURL()
})
});
});
return Promise.all(promises);
}
或更短:
function url_array_get(){
let user=firebase.auth().currentUser;
let ref = firebase.storage().ref('data/'+user.uid+'/posts/');
let files=Array.from(review_photo.files);
let promises = files.map(function(file) {
return ref.child(file.name).put(file).then(function(snapshot){
return snapshot.ref.getDownloadURL()
})
});
return Promise.all(promises);
}