Javascript / реагировать - асинхронно / ожидать с для запросов POST цикла - PullRequest
0 голосов
/ 20 ноября 2018

Я создаю конвертер изображений, где мой JS-код получает входные данные от пользователя, отправляет их на серверную часть Python, где они конвертируются и сохраняются в папке.Затем Python отправляет ответ обратно в JS (реагировать), который обновляет состояние каждого файла в отдельности как «преобразованный» и повторно отображает необходимые компоненты.

У меня есть цикл for, который отправляет отдельные запросы POST для каждогофайл.Это нормально, пока я не захочу создать .zip для всего каталога после того, как все файлы будут конвертированы.Моя проблема лежит там.Мой zip-файл всегда возвращается пустым или с неполными файлами.

// function which takes the file inputs from user
uploadBatch = async () => {
  const files = this.getFilesFromInput();
  const batch = Math.floor(Math.random() * 999999 + 100000);
  for (let i = 0; i < files.length; i++) {
    // sets the state which will then be updated
    await this.setState(
      {
        files: [
          ...this.state.files,
          {
            // file state values
          }
        ]
      },
      () => {
        const formData = new FormData();
        // appends stuff to form data to send to python
        axios
          .post('/api/upload', formData, {
            headers: {
              'Content-Type': 'multipart/form-data'
            },
            responsetype: 'json'
          })
          .then(response => {
            // update the state for this particular file
          });
      }
    );
  }
  return batch;
};

// function which zips the folder after files are converted
handleUpload = async e => {
  e.preventDefault();
  // shouldn't this next line wait for uploadBatch() to finish before 
  // proceeding?
  const batch = await this.uploadBatch();
  // this successfully zips my files, but it seems to run too soon
  axios.post('/api/zip', { batch: batch }).then(response => {
    console.log(response.data);
  });
};

Я использовал async / await, но не думаю, что использовал их хорошо.Я не совсем понимаю эту концепцию, поэтому объяснение будет с благодарностью.

1 Ответ

0 голосов
/ 20 ноября 2018

Всякий раз, когда вы вызываете setState(), компонент будет повторно визуализироваться. В идеале вы должны выполнить все свои действия и позвонить setState() в конце.

Что-то вроде этого должно заставить вас работать

// function which takes the file inputs from user
uploadBatch = async () => {
  const files = this.getFilesFromInput();
  const batch = Math.floor(Math.random() * 999999 + 100000);
  const files = [];
  for (let i = 0; i < files.length; i++) {
    const formData = new FormData();
    // appends stuff to form data to send to python
    const res = 
      await axios
        .post('/api/upload', formData, {
          headers: {
            'Content-Type': 'multipart/form-data'
          },
          responsetype: 'json'
        });

    files.push('push data into files arr');
  }

  return { files, batch };
};

// function which zips the folder after files are converted
handleUpload = async e => {
  e.preventDefault();
  // get batch and files to be uploaded and updated
  const { files, batch } = await this.uploadBatch();
  // this successfully zips my files, but it seems to run too soon
  await axios.post('/api/zip', { batch: batch }).then(response => {
    console.log(response.data);
  });

  // set the state after all actions are done
  this.setState( { files: files });
};
...