我正在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函数中返回或做什么吗?
任何建议表示赞赏
谢谢
答案 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();
})