javascript - Firebase 网站 : upload multiple files to Storage an then download their URLs

标签 javascript firebase firebase-realtime-database firebase-storage es6-promise

我正在创建一个博客网站,并正在编写按顺序执行以下操作的代码:
1.存储用户上传的多张照片
2.下载他们的网址
3.将它们保存到实时数据库中。

我编写了下面的函数来执行 #1 和 #2。基本上,这个想法是将所有 url 存储到一个数组中,在本例中为“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!");    
            });               
        }

问题在于:代码会将除“照片链接”之外的所有内容写入数据库,“照片链接”应该是 URL 数组。
这是我在调试时发现的:
-照片存储没有任何问题。
- 为每个文件下载url,执行代码中按照预期成功返回urlarray。
可能出了什么问题?我在这里迷路了。非常欢迎任何建议。 非常感谢!

最佳答案

每次调用 storageRef.put(...) 时,它都会启动一个异步操作。现在,您的 `` 不会等待这些异步操作完成,而是在填充之前返回 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);
    }
  });
}

当您运行此代码时,输​​出将如下所示:

Starting to put file...

Starting to put file...

Starting to put file...

Resolving with 0 download URLs

Upload done, getting download URL...

Download URL gotten, adding to array...

Upload done, getting download URL...

Download URL gotten, adding to array...

Upload done, getting download URL...

Download URL gotten, adding to array...

这当然不是您想要的顺序,因为您在向数组添加任何下载 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);
}

关于javascript - Firebase 网站 : upload multiple files to Storage an then download their URLs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60207412/

相关文章:

javascript - WebAssembly 返回字符串使用 C

swift - 模拟器在 Firebase 中没有显示错误,但权限被拒绝

java - 我可以使用用户提供的参数在 Android Studio 中创建自定义类,以将数据存储在 Firebase RT DB 中吗

javascript - 如何在 web javascript 中从 firebase 数据库中获取倒数第二个值?

ios - Firebase Offline,确定项目是否保存到服务器而不仅仅是本地缓存

javascript - 从实时Firebase检索数据并以网页上的表格形式显示

PHP 从 gridview 编辑行

javascript - 基于同一模型中的另一个枚举数组设置枚举数组 - Mongoose

javascript - 使用 *ngFor 数组的 Orderby

javascript - Python左移(符号问题)