developit/workerize-loader

Error: Failed to execute 'postMessage' on 'DedicatedWorkerGlobalScope': #<Promise> could not be cloned

wujekbogdan opened this issue · 6 comments

I query a large Firebase collection in my app.
I'd like to offload data traversing to a Web Worker. The .map callback in the code below is the function that blocks the main thread, so I moved it to a Web Worker.

// worker.js
import { db } from '../client';

// eslint-disable-next-line
export const getCollection = async (collection) => {
  const ref = await db.collection(collection).get();

  return ref.docs.map((doc) => {
    const data = doc.data(); // When I remove this line the error is gone

    return Object.defineProperty(data, 'id', {
      value: doc.id,
      enumerable: false,
      writable: false,
    });
  });
};

When I run the worker as follows:

// app.js
import Worker from 'workerize-loader!./worker';

const worker = new Worker();
worker.getCollection('collection'); // Causes an error

The worker.getCollection('collection') call causes:

Error: Failed to execute 'postMessage' on 'DedicatedWorkerGlobalScope': #<Promise> could not be cloned

I found that the problem is somehow related to the doc.data() call. If I comment out that line, the error is gone. The same code, when it's not ran as a WebWorker thread, works fine.

Is it a bug in workerize or is it me doing something wrong?

You need to await the promise from .data() before returning.

// worker.js
import { db } from '../client';

// eslint-disable-next-line
export const getCollection = async (collection) => {
  const ref = await db.collection(collection).get();

-  return ref.docs.map((doc) => {
-    const data = doc.data();
+  return Promise.all(ref.docs.map(async (doc) => {
+    const data = await doc.data();

    return Object.defineProperty(data, 'id', {
      value: doc.id,
      enumerable: false,
      writable: false,
    });
-  });
+  }));
};

You need to await the promise from .data() before returning.

The .data() method is not asynchronous. It doesn't return a Promise.

The same code, when it is executed outside a WebWorker works fine.

There's a Promise somewhere in the value being returned from this method. Perhaps it's a property of the object returned by data(), even if its not data itself.

I'm having this issue too, any fix for this yet?

I'm having this issue too, any fix for this yet?

I fix it. I simply returned doc.data() instead.

I'm going to close this issue out - it isn't something we can solve in workerize-loader. Just make sure not to leave Promises in the objects returned by your workerized functions and things should work fine.