JavaScript:如何在同步代码中使用异步 FileReader?

标签 javascript ajax asynchronous request multipartform-data

我有以下同步工作的代码。基本上它接受 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/

相关文章:

python - gobject.MainLoop 和 tornado.IOLoop 一次?

c# - 如何根据登录成功在新窗口/选项卡或同一窗口/选项卡中打开页面?

javascript - 获取错误 : TypeError: window. 事件在 firefox 中未定义我的 javascript 代码

javascript - Jquery 按变量向左或向右动画

javascript - 使用angularJs显示来自socket io的数据

javascript - 为操作完成而调用 Node 异步回调

javascript - 我可以在 Javascript 中创建一个按顺序但不一定按顺序匹配字符的正则表达式吗?

jquery - 使用 ajax 从 mysql 获取 highchart 数据

php - 使用 php Ajax 将 json 发送到服务

javascript - 如何在文本框未聚焦时关闭 JavaScript 文件?