无法在“Worker”上执行“postMessage”:无法克隆 FormData 对象

Posted

技术标签:

【中文标题】无法在“Worker”上执行“postMessage”:无法克隆 FormData 对象【英文标题】:Failed to execute 'postMessage' on 'Worker': FormData object could not be cloned 【发布时间】:2019-03-10 21:48:25 【问题描述】:

我正在使用网络工作者通过使用切片创建块来上传更大的文件,但是当我以 formData 对象的形式发送文件时,它会抛出这个错误。当我在 reactjs 中这样做时,它会抛出以下错误

react-dom.development.js:518 警告:React 无法识别 DOM 元素上的 offClick 属性。如果您有意希望它作为自定义属性出现在 DOM 中,请将其拼写为小写 offclick。如果您不小心从父组件传递了它,请将其从 DOM 元素中移除。

这是我的代码,我使用 postMessage 将 formData 对象传递给工作人员,请帮我解决这个问题

<!DOCTYPE html>
<html>
<head>
    <title>Using FileReaderSync Example</title>
    <script id="worker1" type="javascript/worker">
             var file = [], p = true;
function upload(blobOrFile) 
    var xhr = new XMLHttpRequest();
    xhr.open('POST', 'url', true);//add url to upload
    xhr.onload = function(e) 
    ;
    xhr.send(blobOrFile);


function process() 
    for (var j = 0; j <file.length; j++) 
        var blob = file[j];

        const BYTES_PER_CHUNK = 1024 * 1024;
        // 1MB chunk sizes.
        const SIZE = blob.size;

        var start = 0;
        var end = BYTES_PER_CHUNK;

        while (start < SIZE) 

            if ('mozSlice' in blob) 
                var chunk = blob.mozSlice(start, end);
             else 
                var chunk = blob.slice(start, end);
            

            upload(chunk);

            start = end;
            end = start + BYTES_PER_CHUNK;
        
        p = ( j = file.length - 1) ? true : false;
        self.postMessage(blob.name + " Uploaded Succesfully");
    

self.addEventListener('message', function(e) 
    for (var j = 0; j < e.data.files.length; j++)
        file.push(e.data.files[j]);
    if (p) 
        process()
    
)
    </script> 
     <script>

       var blob = new Blob([document.querySelector('#worker1').textContent]);
        var worker = new Worker(window.URL.createObjectURL(blob));
worker.onmessage = function(e) 
    alert(e.data);
;
worker.onerror =werror;
function werror(e) 
    console.log('ERROR: Line ', e.lineno, ' in ', e.filename, ': ', e.message);

function handleFileSelect(evt) 
    console.log("coming");
    evt.stopPropagation();
    evt.preventDefault();
     let files = new FormData();
        files.append('file', event.target.files );

    //var files = evt.target.files;
    // FileList object.
    worker.postMessage(
        'files' : files
    );
    //Sending File list to worker
    // files is a FileList of File objects. List some properties.
    var output = [];
    for (var i = 0, f; f = files[i]; i++) 
        output.push('<li><strong>', escape(f.name), '</strong> (', f.type || 'n/a', ') - ', f.size, ' bytes, last modified: ', f.lastModifiedDate ? f.lastModifiedDate.toLocaleDateString() : 'n/a', '</li>');
    
    document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>';


function handleDragOver(evt) 
    evt.stopPropagation();
    evt.preventDefault();
    evt.dataTransfer.dropEffect = 'copy';
    // Explicitly show this is a copy.

function getd()
document.getElementById('files').addEventListener('change', handleFileSelect, false);

window.addEventListener("load", getd, false);
    </script>
</head>
<body>
        <input type="file" id="files" name="files[]"/>
        <output id="list"></output>
</body>
</html>

【问题讨论】:

代码不见了……能补充一下吗? 首先你有一个类型p = ( j = file.length - 1) ? true : false;它是p = ( j == file.length - 1) ? true : false; 对此的任何更新。在响应中面临与网络工作者完全相同的问题。 【参考方案1】:

您没有正确使用工作人员 API。你应该看看这个https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers

您的工作人员文件应如下所示:

self.onmessage = function(e) 

  // Do all the work here the postMessage the result
  self.postMessage(result)

你的“主”文件很好:)

const worker = new Worker('yourWorkerFilePath')

worker.onmessage() = function(resultFormWorker) 
  // treate the result here


worker.postMessage(file)

【讨论】:

以上是关于无法在“Worker”上执行“postMessage”:无法克隆 FormData 对象的主要内容,如果未能解决你的问题,请参考以下文章

临时变量如何在 Worker 上可用

Web Worker

并发编程之Master-Worker模式

web worker的用法及应用场景 (转)

web worker的用法及应用场景 (转)

在 Elastic Beanstalk 上启动 SQS celery worker