Skip to content

Instantly share code, notes, and snippets.

@rwaldron
Created August 25, 2010 22:56
Show Gist options
  • Select an option

  • Save rwaldron/550459 to your computer and use it in GitHub Desktop.

Select an option

Save rwaldron/550459 to your computer and use it in GitHub Desktop.
/*
The constructor
It takes the worker file name as an argument
*/
var worker = new Worker('worker-javascript-file.js')
/*
The postMessage() function sends a message to the worker
*/
worker.postMessage(message)
/*
The onmessage event receives messages from the worker
*/
worker.onmessage = function (event) {
/*
The message is packaged in the event object
The property of interest is:
data
*/
console.log( event.data )
}
/*
In my slides, I lobby against the use of
onmessage = function () {} syntax,
instead encouraging developers to use
the addEventListener() syntax
*/
worker.addEventListener('message', function (event) {
console.log(event.data);
}, false);
/*
the onerror event is triggered if an error occurred.
*/
worker.onerror = function (event) {
/*
The onerror event does not bubble and can be canceled.
The default action can be prevented with
event.preventDefault()
The properties on interest are:
message, filename, lineno
*/
}
/*
The terminate() function is supposed
to stop a Worker from executing immediately
*/
worker.terminate()
/*
The Worker object also implements the following:
*/
worker.addEventListener()
worker.removeEventListener()
worker.dispatchEvent()
/*
The Worker: WorkerGlobalScope
Inside the worker, the keywords "self" and "this"
are the same thing and both are the equivalent
to the global WorkerGlobalScope
*/
self = this = [WorkerGlobalScope]
/*
The postMessage() function sends a message
from the worker to the main execution thread
*/
self.postMessage(message)
/*
The onmessage event receives messages
from the main execution thread
*/
self.onmessage = function (event) {
/*
The message is packaged in the event object
The property of interest is:
data
*/
}
/*
As with the example in the main window,
I'd like to encourage developers to use
the addEventListener() syntax
*/
self.addEventListener('message', function (event) {
this.postMessage(event.data);
}, false);
/*
The importScripts() function can be used
to call in reusable libraries
But there is a drawback here - all the major
libraries that exist will throw exceptions
if the developer tries to import them into the
WorkerGlobalScope - they all reference either
"window" or "document" - both of which are
considered "non thread safe".
Because of this, developers are left to
"roll their own" reusable libraries, which
is both inefficient and counter productive.
*/
self.importScripts(urls)
/*
WorkerGlobalScope also implements
the following interfaces:
*/
self.addEventListener()
self.removeEventListener()
self.dispatchEvent()
self.setTimeout()
self.clearTimeout()
self.setInterval()
self.clearInterval()
/*
As well as:
*/
self.location
self.navigator
/*
And
*/
new XMLHttpRequest
// However, requestXML and channels properties are NULL
// This script is executed in the main window
/*
we'll use a worker to filter a huge data set
for all entries that match our filter string "foo"
*/
var worker = new Worker('worker-javascript-file.js'),
message = {
fn: 'filterHugeDataSet',
data: { /* huge data object */ },
filter: 'foo'
};
/*
For this to work the same way in both Gecko and WebKit,
we'll need to stringify the object before sending it
Now it looks like this:
"{"fn":"filterHugeDataSet","data":{},"filter":"foo"}"
*/
worker.postMessage(JSON.stringify(message));
/*
When the worker has filtered the data and returns it
to our application's main window thread,
we'll need to translate it back into an object manually
*/
worker.addEventListener('message', function (event) {
var filtered = JSON.parse(event.data);
console.log(filtered);
}, false);
// This script is executed in the worker
var filters = {
filterHugeDataSet: function (data, filter) {
// do some kind of filtering...
// this is crummy, but you get the idea
var obj = {};
for ( var key in data ) {
if ( key == filter ) {
obj[key] = data[key];
}
}
return obj;
}
};
/*
The worker will begin running when it receives
a message from the main window.
The first thing it will have to do is parse the
message back into object.
*/
self.addEventListener('message', function (event) {
var message = JSON.parse(event.data),
filtered = {};
/*
`message` is now an object again. and looks how
you expect it to:
message = {
fn: 'filterHugeDataSet',
data: { foo:'bar' },
filter: 'foo'
};
Use your imagination here...If we had an object
called "filters" with a function property called
"filterHugeDataSet" we could now call it with
the params we passed along with the data
*/
filtered['data'] = filters[message.fn](message.data, message.filter);
/*
Now we want to send it back. Once again we'll
manually serialize the object
*/
this.postMessage(filtered);
}, false);
// The main window
$(function () {
var message = {
data: { /* huge data object */ },
filter: 'foo'
};
$.Hive.create({
// optional. if no 'count' property is set, Hive creates only 1 worker
count: 1,
// the worker file
worker: 'hive-worker-file-1.js',
// the receive ( convenience to writing out the addEventListener)
receive: function (filtered) {
/*
jQuery.Hive manages serialization/deserialization
*/
console.log(filtered.data);
},
created: function ( $hive ) {
/*
the `created` callback fires after the worker is created,
the first argument is an array of the workers
$().send() is the wrapper for postMessage() with complete
serialization/deserialization
*/
$( $hive ).send(message);
}
});
/*
without comments:
$.Hive.create({
worker: 'hive-worker-file-1.js',
receive: function (filtered) {
console.log(filtered.data);
},
created: function ( $hive ) {
$( $hive ).send(message);
}
});
*/
});
// Inside the worker
importScripts('jquery.hive.pollen.js');
// Alias to addEventListener() syntax
$(function (message) {
// $.send() is the wrapper for postMessage() with complete
// serialization/deserialization
$.send(
// $.query() is part of the PollenJS API
$.query(
// Filter data with a JSONPath query
"[="+message.filter+"]",
message.data
)
);
});
/*
without comments:
importScripts('jquery.hive.pollen.js');
$(function (message) {
$.send(
$.query(
"[="+message.filter+"]",
message.data
)
);
});
*/
jQuery.Hive -> The Hive is a property of jQuery
jQuery.Hive.options -> Setup properties for jQuery.Hive.create( [options] )
jQuery.Hive.options.count -> Set property from jQuery.Hive.create( { count: [int] } ), number of threads to create
jQuery.Hive.options.worker -> Set string property from jQuery.Hive.create( { worker: [file-name] } ), name of worker file
jQuery.Hive.options.receive -> Set callback from jQuery.Hive.create( { receive: [callback] } ), callback to execute when worker receives message (can be global or worker specific)
jQuery.Hive.options.created -> Set callback from jQuery.Hive.create( { created: [callback] } ), callback to execute when workers have been created
jQuery.Hive.options.special -> NOT IMPLEMENTED/INCOMPLETE - Set callback as a second argument to $().send()
jQuery.Hive.options.error() -> NOT IMPLEMENTED/INCOMPLETE - Error handler
jQuery.Hive.create( options ) -> Array, create workers, returns array of all workers
jQuery.Hive.destroy( [id] ) -> destroy all or specified worker by id
jQuery.Hive.get( [id] ) -> Return all or specified worker by [id], [id] argument is optional
--> $.Hive.get() returns all worker objects in the $.Hive
--> $.Hive.get(1) returns the worker object whose ID is 1
jQuery.Hive.get( id ).send( message, callback ) -> Send [message] to worker thread, set optional receive callback
--> SIMPLER ALTERNATIVE: $.Hive.get(id).send( [message], function () {} )
--> Allows for passing a jQuery.Hive.get(id) object to $() ie. $( $.Hive.get(id) ).send( [message] )
jQuery.( $.Hive.get() ).send( message ) -> Send [message] to worker thread
--> SIMPLER ALTERNATIVE: $.Hive.get(id).send( [message] )
--> Allows for passing a $.Hive.get(id) object to $() ie. $( $.Hive.get(id) ).send( [message] )
$.now([uts]) -> Microseconds or UTS if $.now(true)
$.noop() -> Empty function, Lifted from jQuery 1.4+, returns empty function (replaced $.emptyFn())
$.bind( function, context, args ) -> Function with explicit context, context sets 'this'
$.isObj( arg ) -> Boolean, object was created with {} or new Object()
$.isEmptyObj( arg ) -> Boolean, Empty Object
$.isArr( arg ) -> Boolean, Array
$.isRegExp( arg ) -> Boolean, Regular Expression
$.isFn( arg ) -> Boolean, Function
$.isStr( arg ) -> Boolean, String
$.isNum( arg ) -> Boolean, Number
$.isJson( arg ) -> Boolean, Valid JSON String
$.isDef( arg ) -> Boolean, Defined
$.isNull( arg ) -> Boolean, Null
$.isEmpty( arg ) -> Boolean, ''
$.eq( arg, array ) -> Arg is equal to at least one definition in array
$.trim( arg ) -> Removes all L and R whitespace
$.inStr( arg ) -> Boolean, arg in string
$.each( object, function ) -> Enumerate [object] (object,array), apply [function]
$.toArray( arg ) -> Convert [arg] into an array
$.isAtIndex( array, index, needle ) -> Boolean, Checks if [needle] is located at [index] in [array]
$.getIndex( array, needle ) -> Int, index of [needle] in [array]
$.inArr( array, needle ) -> Boolean, true if [needle] in [array]
$.clone( arg ) -> Array || Object, clone of [array] or Object, deep clone of [object]
$.last( array ) -> Array Item, last item in [array]
$.first( array ) -> Array Item, first item in [array]
$.unique( arg ) -> Array || Object, removes duplicate values from [arg](array||object), returns uniques
$.merge( arr, ) -> Array, Merges [*](array), removes duplicate values
$.combine( keys, values ) -> Object, An object, where [keys](array) = [values](array)
$.filter( arg , function, iteration ) -> (Array||Object), apply [function](true||false) to each item in [arg], return (array||object) of true
$.map( array, function ) -> Array, apply [function] to each item in [array], return array of new values
$.grep( array, expression, function ) -> Object, values that match [expression] and/or [function]
$.size( array ) -> Int, size of arr
$.extend( object, _object ) -> Object, copy properties fron [_object] to [object]
$.ajax.get( request ) -> Implemented. Documention incomplete.
--> request.url -> url to open
--> request.data -> params
--> request.success -> success callback
$.ajax.post( request ) -> Implemented. Documention incomplete.
--> request.url -> url to open
--> request.data -> params
--> request.success -> success callback
$.param( arg ) -> String, Derived and Adapted from, similar in behavior to jQuery.param()
$.storage( key, val ) -> ?, persistant across worker messages (by worker) data storage - setter
$.storage( key ) -> Val, persistant across worker messages (by worker) data storage - getters
$.query( selector, object ) -> *, Query json or object with JSONPath selector
--> http://goessner.net/articles/JsonPath/
$.send( message ) -> Wraps and normalizes postMessage() across supporting clients, sends [message](object||string||array) to client
--> if [message] is an object, and message.SEND_TO & message.SEND_FROM is defined, the message will be sent directly to the worker defined by SEND_TO
$.receive( function() {} ) -> Worker, execute [function] when worker receives a message from the client
--> first argument is message object
--> 'this' is WorkerGlobalScope
--> can be shortened to $(function (message) { } );
$.decode( arg ) -> JSON as String, turns JSON [arg] into a str
$.encode( arg ) -> JSON Object, turns [arg] into JSON
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment