【问题标题】:Calling Papa.parse in worker with _config.worker = false calls postMessage使用 _config.worker = false 在 worker 中调用 Papa.parse 调用 postMessage
【发布时间】:2026-01-03 13:50:02
【问题描述】:

我在自己的工作人员中调用 Papa.parse,而在 _config.worker 中设置为 false。 当进程完成时,它调用postMessage 仍然会触发一条消息给我自己的工作人员。 不应该this

if (IS_PAPA_WORKER)
{
    global.postMessage({
        results: results,
        workerId: Papa.WORKER_ID,
        finished: finishedIncludingPreview
    });
}

还应该检查config.worker 是否设置为true 然后只调用global.postMessage 我不想将结果发送到主线程任何想法如何实现它?

【问题讨论】:

    标签: javascript web-worker papaparse worker-loader


    【解决方案1】:

    他们做define IS_PAPA_WORKER

    var IS_WORKER = !global.document && !!global.postMessage,
        IS_PAPA_WORKER = IS_WORKER && /blob:/i.test((global.location || {}).protocol);
    

    这意味着他们会检查是否没有 document 属性、postMessage 属性以及当前领域是否已从 blob: URI 加载。

    在您的情况下,最好的解决方案可能是不从 blob: URI 加载您的脚本,而是使用专用的脚本文件。

    const worker = new Worker( '/a_real_file.js' );
    

    这是一个使用 data: URI 的演示,因为 StackSnippets 不允许存储文件,但自己不要使用 data: URI,这只是为了演示协议很重要:

    const worker_script = document.querySelector( '[type="worker-script"]' ).textContent;
    const worker_url = 'data:text/javascript,' + encodeURIComponent( worker_script );
    const worker = new Worker( worker_url );
    worker.onmessage = ({data}) => console.log( data );
    worker.onerror = console.error;
    <script type="worker-script">
      importScripts( 'https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.1.0/papaparse.min.js' );
      
      const csv = `col1,col2,col3
    a,1,z
    b,2,y
    c,3,x`;
      Papa.parse( csv, { header: true } );
      postMessage( 'worker done' );
    </script>

    现在,如果您绝对需要使用 blob: URI,最简单的解决方案是在导入库之前将 document 定义为真实的全局属性:

    const worker_script = document.querySelector('[type="worker-script"]').textContent;
    const worker_url = URL.createObjectURL( new Blob( [ worker_script ], { type: 'text/javascript' } ) );
    const worker = new Worker( worker_url );
    worker.onmessage = ({data}) => console.log( data );
    <script type="worker-script">
      self.document = {};
      importScripts( 'https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.1.0/papaparse.min.js' );
      
      const csv = `col1,col2,col3
    a,1,z
    b,2,y
    c,3,x`;
      Papa.parse( csv, { header: true } );
      postMessage( 'worker done' );
    </script>

    【讨论】:

    • 有效。我没有检查worker-loader inline 会将其作为 blob 导入。谢谢
    【解决方案2】:

    谁在webapck 中使用worker-loader 不要使用内联导入

    this.worker = await import(/* webpackChunkName: "MyWorker" */ 'workers/MyWorker')this import it as BLOB

    使用import MyWorker from 'worker-loader!./MyWorker.js'; 导入它,这会将其作为文件导入,不会引起问题。

    【讨论】: