使用诺言完成一项任务,然后再执行另一项任务

时间:2019-01-02 23:49:20

标签: vue.js es6-promise

我正在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 :(得分:2)

这里的第一个问题是您的processCSVFile函数不会返回Promise。不幸的是,Papa Parse functions“不返回任何内容。结果异步提供给回调函数。”但是,由于它们采用了回调,因此您可以轻松地将调用包装在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);
        }
      });
    });
}

Promise API的优点之一是它可以轻松链接。特别是,从任何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();
  }
}

答案 1 :(得分:0)

您要在此处执行的操作是让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();
})