Задать вопрос
@fisherspoons

Как дождаться полной загрузки файла перед загрузкой следующего?

Есть компонент для загрузки файлов, в котором есть область для загрузки. При отправке запроса для каждого файла нужно прокидывать в запросе позицию(filePosition) каждого файла, которую я хочу добавлять на основании длинны массива в который добавляются все объекты файлов после их загрузки. Проблема в том что при вызове fetch для каждого файла нужно чтобы сначала заходило в then где пушатся объекты в массив, соответсвенно меняя длину массива, но сначала происходит вызов всех fetch а только потом then. Я так понимаю что нужно как-то переписать с async await, но придумать как не получается, прошу не хейтить

child component method
attachThumbnail: async function (e, curObj){
        e.target.closest('.area-upload').classList.remove('drag-file');
        e.target.closest('.area-upload').style.display = 'flex';

        let files = e.target.files || e.dataTransfer.files;
        let allowFiles = this.validateFiles(e, files, curObj);

        Array.from(allowFiles).forEach((file, index) => {
          this.$emit('attachThumbnail', curObj, file)
        });
      },


parent component
formData: {
        materialFiles: [
          {
            lang: 'uk',
            files: {
              profile: {
                name: '',
                id: ''
              },
              preview: {
                name: '',
                id: '',
                link: ''
              },
              restFiles: []
            }
          },
        ],
      },



 attachThumbnail(curObj, file){
      let index = this.formData.materialFiles.findIndex(item => item.lang === curObj.lang);
      let filePosition = this.formData.materialFiles[index].files.restFiles.length

      console.log('Array length ' + filePosition)

      this.uploadFile(curObj, file,'rest', filePosition)
          .then(response => response.json())
          .then(data => {
            console.log('append file')
            this.formData.materialFiles[index].files.restFiles.push({
              name: data.fileName,
              id: data.id
            })
          })
          .catch(error => {
            console.log(error)
          })
    },

uploadFile(curObj, file, type, position) {
      this.addPreloader = true
      let formData = new FormData(),
          data ={
            document: file,
            type: type,
            lang: curObj.lang,
            isPreview: type === 'preview',
            position: type === 'rest' ? position : 0
          }

      for (let key in data) {
        formData.append(key, data[key]);
      }
      return fetch('/api/material_media', {
        method: 'POST',
        body: formData,
      })
    },


<b>dev tools</b>
2 Array length 0
2 append file
  • Вопрос задан
  • 167 просмотров
Подписаться 1 Простой Комментировать
Помогут разобраться в теме Все курсы
  • Нетология
    Fullstack-разработчик на Python + нейросети
    20 месяцев
    Далее
  • Skillfactory
    Профессия Веб-разработчик
    12 месяцев
    Далее
  • Академия Eduson
    Fullstack-разработчик на JavaScript
    11 месяцев
    Далее
Пригласить эксперта
Ответы на вопрос 1
@7rows
Frontend Разработчик / Vue / JS / TS / CSS
Проблема в том, что все fetch запросы запускаются параллельно, и filePosition вычисляется до того, как предыдущие файлы успевают добавиться в массив. Вот несколько способов решения:

// В дочернем компоненте - передаем все файлы сразу
attachThumbnail: function (e, curObj) {
  e.target.closest('.area-upload').classList.remove('drag-file');
  e.target.closest('.area-upload').style.display = 'flex';

  let files = e.target.files || e.dataTransfer.files;
  let allowFiles = this.validateFiles(e, files, curObj);

  this.$emit('attachThumbnail', curObj, Array.from(allowFiles));
},

// В родительском компоненте - обрабатываем последовательно
async attachThumbnail(curObj, files) {
  let index = this.formData.materialFiles.findIndex(item => item.lang === curObj.lang);
  
  for (let i = 0; i < files.length; i++) {
    let file = files[i];
    let filePosition = this.formData.materialFiles[index].files.restFiles.length;

    console.log('Array length ' + filePosition);

    try {
      const response = await this.uploadFile(curObj, file, 'rest', filePosition);
      const data = await response.json();
      
      console.log('append file');
      this.formData.materialFiles[index].files.restFiles.push({
        name: data.fileName,
        id: data.id
      });
    } catch (error) {
      console.log(error);
    }
  }
}


Примерно как-то так
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы