问题
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.
回答1:
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());
});
回答2:
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
, orauthWithOAuthRedirect
will throw an exception. Instead, use your own server for login and callauthWithCustomToken
. - 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.
来源:https://stackoverflow.com/questions/33520936/is-there-an-easy-way-to-run-firebase-in-a-web-worker