Search code examples
javascriptweb-workerpapaparseworker-loader

Calling Papa.parse in worker with _config.worker = false calls postMessage


I am calling Papa.parse in my own worker and in _config.worker is set false. When process completes it calls postMessage still that triggers a message to my own worker. Shouldn't this

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

Should also check if config.worker is set to true then only call global.postMessage I don't want to send results to main thread any idea how can i achieve it ?


Solution

  • They do define IS_PAPA_WORKER to

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

    This means they do check is there is no document property, a postMessage property, and if the current realm has been loaded from a blob: URI.

    The best solution in your case is probably to not load your script from a blob: URI, but instead use a dedicated script file.

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

    Here is a demo using a data: URI, since StackSnippets don't allow storage of files, but don't use data: URIs yourself, it's just for demo the protocol matters:

    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>

    Now if you absolutely need to use a blob: URI, the simplest solution is to define document as a truthy global property before you import the library:

    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>