简体   繁体   中英

Is there an easy way to run Firebase in a web worker?

I have a single page React application which consists of many files, bundled with gulp/browserify.

Firebase javascript is embedded in this bundle.

I'd like to know if there is an easy way to run certain Firebase operations on another worker thread ?


What I have tried :

Setting up a worker and sending the Firebase object, or instance, via worker.postMessage(xxx) . In both cases, it throws an error which says the object cannot be cloned . Example bellow with the Firebase object.

var blobURL = URL.createObjectURL(new Blob([ '(',
    (function() {
        var onmessage = function(event) {
            var FB = new event.data.Firebase('my firebase URL');
            // Here, some Firebase operations
            // ...
        };
    }).toString(),
')()' ], { type: 'application/javascript' }));
var postViewedWorker = new Worker(blobURL);
URL.revokeObjectURL(blobURL);

[... later on ...]

postViewedWorker.postMessage({Firebase: Firebase, ...otherParams});

In the above example, the Worker works (haha) until I try to pass Firebase.


What I would like to avoid :

Setting two completely different bundles, one with the main application, and one dedicated to all Firebase operations, with a helper lib to send operations from one another.


Note : The reason behind this question is because my UI is slowed by Firebase operations. For example, I have a list of items displayed on a page, and when I scroll, each time an item is visible, the view count of this object is updated with Firebase. The page scrolling is smooth without those operations, and becomes jerky when I add them.

Edit: Also, I consistently get the following warning : Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience.

Easy, depends on your values for easy. Possible, definitely.

I used microdom to get it working. Here's a rough/dirty version, bundle as makes sense to you.

In your worker:

 importScripts("http://raw.github.com/tmpvar/microdom/master/microdom.min.js"); var window = microdom('<html></html>'); var document = window; importScripts("https://cdn.firebase.com/js/client/2.4.2/firebase.js"); var ref = new Firebase(input.firebase_endpoint); // This ref now works, authenticates, etc. You can use .notify() to pass info to the main thread, etc. ref.on("value", function(snapshot) { output.notify(snapshot.val()); }); 

I have a working open source implementation that puts Firebase into a worker: https://github.com/pkaminski/fireworker . It can use both plain and shared workers (where supported) and integrates extra features from other Firebase add-on libraries. It emulates the Firebase API and automatically bridges calls from the main page to the worker, so your existing code should more-or-less continue to work as-is. It also has some non-trivial limitations, as of this writing:

  • Only supports Firebase SDK 2.4.2. Could probably be adapted to SDK 3.x but it's going to be harder since the source code is not available.
  • Interactive authentication methods don't work; calling authWithPassword , authWithOAuthPopup , or authWithOAuthRedirect will throw an exception. Instead, use your own server for login and call authWithCustomToken .
  • Item priority is not currently implemented. Because priority is stored out of band it's difficult to support efficiently, and Firebase folks have indicated that it's essentially deprecated anyway.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM