Выполнение одной задачи перед выполнением другой с помощью обещаний - PullRequest
0 голосов
/ 03 января 2019

Я работаю в VueJS.У меня есть простая форма, где у меня есть файл ввода плюс еще одно поле.

<form @submit.prevent="formSubmit()">
    <div class="card-body">
        <div class="form-group">
            <label for="someName">Some Name</label>
            <input type="text" class="form-control" id="someName"
                   placeholder="someName" v-model="form.someName">
        </div>
        <div class="form-group">
            <label for="uploadedFile">Data</label>
            <input type='file' ref="file" @change='handleCSVUpload' accept=".csv"
                   id="uploadedFile">
        </div>
    </div>
    <button class="btn btn-success">Submit</button>
</form>

Итак, что я хочу сделать, это как только я добавляю файл, я хочу назначить его переменной данных,Таким образом, у меня есть @change, который вызывает это

export default {
    data() {
        return {
            csvFile: '',
            parsedData: '',
            form: new Form({
                someName: ''
            })
        }
    },
    methods: {
        handleCSVUpload() {
            this.csvFile = this.$refs.file.files[0];
        }
    }
}

Это все хорошо.Моя проблема приходит дальше.Когда форма отправлена, я хочу сначала проанализировать этот файл в JSON.Как только это будет сделано, я хочу отправить этот JSON в бэкэнд вместе с другим полем формы.На данный момент у меня есть это

import Papa from 'papaparse';

export default {
    data() {
        return {
            csvFile: '',
            parsedData: '',
            form: new Form({
                someName: ''
            })
        }
    },
    methods: {
        handleCSVUpload() {
            this.csvFile = this.$refs.file.files[0];
        },
        formSubmit() {
            this.$Progress.start();

            this.processCSVFile(this.csvFile);

            this.form.post('api/upload').then(() => {
                this.$Progress.finish();
            }).catch(() => {
                this.$Progress.fail();
            })
        },
        processCSVFile(csv) {
            let file = csv;
            let config = {
                delimiter: "",
                newline: "",
                quoteChar: '"',
                escapeChar: '"',
                header: true
            };

            Papa.parse(file, {
                config: config,
                error: function (err, file) {
                    console.log("ERROR:", err, file);
                    return err;
                },
                complete: function (results) {
                    this.parsedData = JSON.stringify(results.data);
                    console.log(this.parsedData)
                }
            });
        }
    }
}

Это все прекрасно работает, но не очень доволен этим.В методе formSubmit, который я называю this.processCSVFile(this.csvFile);, я сразу же отправляю данные в бэкэнд.Вместо этого мне нужно убедиться, что с парсингом все в порядке, потому что если нет, мне нужно отобразить ошибку и ничего не отправлять.Теперь следующее неверно, но оно показывает мое мышление

this.processCSVFile(this.csvFile).then(() => {
  this.form.post('api/upload').then(() => {
    this.$Progress.finish();
  }).catch(() => {
    this.$Progress.fail();
  })

Таким образом, он должен обработать файл CSV, если это успешно, а затем отправить в API.Тем не менее, не знаете, как выполнить эти многочисленные обещания?Также не слишком уверен, что я должен возвращать или делать в функции processCSVFile?

Любой совет приветствуется

Спасибо

Ответы [ 2 ]

0 голосов
/ 03 января 2019

Первая проблема заключается в том, что ваша функция processCSVFile не возвращает обещание.К сожалению, функции Papa Parse"[не] ничего не возвращают. Результаты предоставляются асинхронно функции обратного вызова".Но так как они принимают обратные вызовы, вы можете легко обернуть вызов в Promise, например, так:

processCSVFile(csv) {
  let config = {...};
  return new Promise((resolve, reject) => {
      Papa.parse(csv, {
        config: config,
        error: reject,
        complete: (results) => {
          this.parsedData = JSON.stringify(results.data);
          resolve(this.parsedData);
        }
      });
    });
}

Одна из приятных особенностей API Promise заключается в том, что он может быть легко связан.В частности, из любого обработчика Promise вы можете вернуть Promise вместо определенного результата.Итак, в приведенном выше коде:

this.processCSVFile(this.csvFile).then(() => {
  return this.form.post('api/upload');
}).then(() => {
  this.$Progress.finish();
}).catch(() => {
  this.$Progress.fail();
});

Ваше сообщение также помечено es6, поэтому вы можете использовать отличный синтаксис async / await.В этом случае вам нужно изменить свою функцию на async, например так:

async formSubmit() {
  this.$Progress.start();
  try {
    await this.processCSVFile(this.csvFile);
    await this.form.post('api/upload');
    this.$Progress.finish();
  } catch (err) {
    this.$Progress.fail();
  }
}
0 голосов
/ 03 января 2019

То, что вы хотите сделать здесь, это processCSVFile вернуть Promise.

Вы можете сделать это, поместив вызов в Papa.parse в новый Promise. Например

processCSVFile (csv) {
  let config = { ... } // no change here
  return new Promise((resolve, reject) => {
    Papa.parse(csv, {
      config,
      error: (err, file) => {
        console.error(err, file)
        reject(err)
      },
      complete: results => {
        resolve(JSON.parse(results.data))
      }
  })
}

Теперь вы можете делать именно то, что вы хотели в вашем обработчике отправки ...

this.processCSVFile(this.csvFile).then(parsedData => {
  this.parsedData = parsedData // you could also do this in processCSVFile
  // note the "return" here so control will bubble up the promise chain
  return this.form.post('api/upload')
}).then(() => {
  this.$Progress.finish();
}).catch(() => {
  // This will catch any failures in "processCSVFile" and / or "this.form.post"
  this.$Progress.fail();
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...