Firebase web: загрузите несколько файлов в хранилище и загрузите их URL - PullRequest
0 голосов
/ 13 февраля 2020

Я создаю веб-сайт для ведения блога и пишу код, который выполняет следующие действия по порядку:
1. хранит несколько фотографий, которые пользователь загружает
2. скачать их URL
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);
    }
});
}

Вот часть кода функции загрузки, которая будет загружать все соответствующие данные в базу данных, включая массив 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.
Вот что я обнаружил при отладке:
-Фотографии сохраняются без проблем.
-рлы загружаются для каждого файла, и urlarray успешно возвращается в коде выполнения, как и ожидалось.
Что может пошло не так? Я потерян здесь. Любой совет будет очень приветствоваться. Большое спасибо!

1 Ответ

1 голос
/ 13 февраля 2020

Каждый раз, когда вы звоните 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);
    }
  });
}

Когда вы запустите этот код, результат будет выглядеть следующим образом:

Начиная с файла ...

Начиная с файла ...

Начало помещения файла ...

Разрешение с 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...