我有以下同步工作的代码。基本上它接受 html 形式并将其元素解析为 url 字符串。
SmFaq.DataForm = function (f) { // f is HTML form
var P = new Array();
/* parsing array */
var params = P.join("&");
return params;
}
效果很好,但现在我需要添加input type="file"
。我根据这篇文章提出了请求:Sending forms with JavaScript(处理二进制数据),除了在请求正文中加载二进制数据之外,一切正常。我的函数在读取文件之前返回字符串。
任务:我需要读取二进制数据并将其添加到请求正文字符串,然后返回该字符串。是否可以?我不在乎 GUI 是否会因加载时间而卡住。
这是我的代码:
SmFaq.DataForm = function (f) {
var name = f.querySelector('#created_by');
var email = f.querySelector('#created_by_email');
var question = f.querySelector('#question');
var file = {
dom: f.querySelector('#file'),
binary: null
};
var reader = new FileReader(); // to read binary data
if (file.dom.files[0]) {
reader.readAsBinaryString(file.dom.files[0]);
}
file.dom.addEventListener('change', function() {
if (reader.readyState === FileReader.LOADING) {
reader.abort();
}
reader.readAsBinaryString(file.dom.files[0]);
});
reader.addEventListener('loadend', function() {
file.binary = reader.result;
console.log('Binary data loaded!');
});
return sendData();
function sendData() {
if (!file.binary && file.dom.files.length > 0) {
setTimeout(sendData, 2000);
return;
}
var boundary = "1234567890";
var data = '';
data += '--' + boundary + '\r\n';
data += 'content-disposition: form-data; '
+ 'name="' + file.dom.name + '";'
+ 'filename="' + file.dom.files[0].name + '"\r\n';
data += 'Content-Type: ' + file.dom.files[0].type + '\r\n';
data += '\r\n';
data += file.binary + '\r\n';
data += '--' + boundary + '\r\n';
data += 'content-disposition: form-data; name="' + name.name + '"\r\n';
data += '\r\n';
data += name.value + '\r\n';
data += '--' + boundary + '\r\n';
data += 'content-disposition: form-data; name="' + email.name + '"\r\n';
data += '\r\n';
data += email.value + '\r\n';
data += '--' + boundary + '\r\n';
data += 'content-disposition: form-data; name="' + question.name + '"\r\n';
data += '\r\n';
data += question.value + '\r\n';
data += '--' + boundary + '--';
data += '\r\n';
return data;
}
}
我不知道这个异步的事情,所以它肯定不能按预期工作。
请不要使用 ES7 功能,我使用遗留代码,不可能使用 Babel。
最佳答案
我认为不可能同步完成。以下是异步执行的方法:
var SmFaq = {};
SmFaq.DataForm = function(f, callback) {
var name = f.querySelector('#created_by'),
file = f.querySelector('#file'),
data = '',
reader = new FileReader();
reader.addEventListener('loadend', function() {
console.log('Here are binary datas !');
data += reader.result;
callback(data);
});
data += 'Created by ';
data += name.value;
data += '\n';
if (file.files[0]) {
data += file.files[0].name;
data += '\n';
data += ' ... ';
data += '\n';
console.log('Waiting for binary datas...');
reader.readAsBinaryString(file.files[0]);
} else {
callback(data);
}
}
function handleData(data) {
// Do whatever you want to do with data
console.log(data);
}
document.getElementById('myForm').addEventListener('submit', function(e) {
e.preventDefault();
SmFaq.DataForm(this, handleData);
});
<form id="myForm">
<input type="text" id="created_by" placeholder="Who Am I ?" /><br />
<input type="file" id="file" /><br />
<input type="submit" value="Submit" />
</form>
更改 DataForm
的调用方式,为其添加回调,并在获得所有数据后调用 callback
函数。然后,您可以在回调函数内处理这些数据,在我的示例中为 handleData
。
关于JavaScript:如何在同步代码中使用异步 FileReader?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47789362/