Weaver.js

Concise and readable parallelism (compatible with CommonJS/Node.js/io.js, AMD/Require.js, npm, Bower, spm, Meteor/Atmosphere, and plain JavaScript)
GitHub Download 1.2.0

Introduction

Expensive calculations can make your app painfully slow for your users. You can make parallelisable code much faster by using Weaver.js, making your app snappier and your users happier.

Factsheet

About

Weaver.js is an open-source parallelism library written in JavaScript. You can use Weaver.js for speeding up your code where parallelisation applies.

Weaver.js is an open-source project, and anyone is free to contribute. For more information, refer to the GitHub README.

Weaver.js was designed and developed by Max Franz.

The .js.org domain for Weaver is provided gratis by JS.ORG.

Packages

Events

Event object

Events passed to handler callbacks are similar to jQuery event objects in that they mimic the API of native event objects.

Fields:

Thread events

Thread

A thread is a reusable object for purposes of parallelism. It gives a simple and concise API that is consistent across JS environments (using WebWorkers on browsers and forked child processes on Node.js).

A thread can be created as follows:

var thread = weaver.thread();

The new keyword and class-style uppercase naming are optional, so you may alternatively do as follows:

var thread = new weaver.Thread();

Minification

When code is run through a minifer like UglifyJS, the names of variables can be mangled. This means that the name specified in your code for a function or object may not be the same when it is minified.

Because Weaver is limited to what JS engines provide in terms of live code inspection, this means that minification can break the references made in thread.run().

In order to minify Weaver-using code, it is necessary to have more fastidious use of references. By explicitly naming references using thread.require( obj, 'obj' ) and _ref_( 'obj' ), minification will work properly.

Globals

The functions that follow are globally accessible inside of thread code (but private to the thread):

_ref_()

Get the specified variable in the thread's scope, preventing minification issues.

_ref_( ,name )
  • name

    The name of the variable to get.

Description

The purpose of this function is to reference a variable in the thread explicitly. This avoids minification from mangling references to things you have required via thread.require() or to thread globals like resolve() or broadcast().

Examples

function foo(){
  return 'bar';
}

var t = weaver.thread();

t.require( foo, 'foo' ); // explicitly specify name to avoid minification issues

t.run(function(){
   // explicitly get by reference to avoid minification issues:
  var foo = _ref_('foo');
  var resolve = _ref_('resolve');

  resolve( foo() );
}).then(function( val ){
  console.log( val ); // bar
});
resolve()

Resolve the thread's run promise with a single value such that other entities (like the main JS thread or other threads) can read it.

Details

This function allows the developer to pass a single value outside of the thread.

Examples

var t = weaver.thread();

t.promise(function(){
  resolve( 3 );
}).then(function( val ){
  console.log( 'thread resolved with `%s`', val );

  t.stop();
});
reject()

Reject the thread's run promise with a single error value such that other entities (like the main JS thread or other threads) can read it.

Details

This function allows the developer to pass a single error value outside of the thread.

Examples

var t = weaver.thread();

t.promise(function(){
  reject( 'some reason' );
}).then(function( val ){
  // does not resolve

}, function( err ){
  console.log( 'thread rejected with `%s`', err );

  t.stop();
});
listen()

Listen to messages sent to the thread.

listen( ,function(msg) )
  • function(msg)

    A function that is called when a message, msg, is received.

Examples

var t = weaver.thread();

t.run(function(){
  listen(function( msg ){
      console.log( 'thread heard: ' + [msg.foo, msg.bar].join(' ') );

    broadcast( msg ); // just send it back
  });
});

t.on('message', function( e ){
  var msg = e.message;

  console.log( 'main js entity/thread heard: ' + [msg.foo, msg.bar].join(' ') );

  t.stop();
});

t.message({ foo: 'hello', bar: 'world' });
broadcast()
Aliases: message(),

Broadcast a message to entities who are listening to the thread.

broadcast( ,msg )
  • msg

    A message, e.g. JSON object or string, that is broadcasted.

Examples

var t = weaver.thread();

t.run(function(){
  listen(function( msg ){
      console.log( 'thread heard: ' + [msg.foo, msg.bar].join(' ') );

    broadcast( msg ); // just send it back
  });
});

t.on('message', function( e ){
  var msg = e.message;

  console.log( 'main js entity/thread heard: ' + [msg.foo, msg.bar].join(' ') );

  t.stop();
});

t.message({ foo: 'hello', bar: 'world' });

Execution

thread.require()
Aliases: thread.include(),

Require a named function into the thread, giving the thread a global reference to the function. Plain objects or simple objects with a prototype (that can be inpected and serialised live) are also supported. Specifying the name of a JS file (i.e. a string ending in '.js') allows for importing external files into the global thread scope.

thread.require( ,obj [,as] )
  • obj

    The named function, simple object, or JS file name to require that is serialised and copied to the thread.

  • as [optional]

    The name of the object as available in the thread. This is mandatory for an object that is not a named function, because its name can not be automatically inferred. This is also mandatory if minification is used, to prevent mangling.

Details

This function allows for pulling external code into the thread. A thread can require

  • a plain JSON-serialisable object,
  • a function that does not reference externals (external functions or external objects),
  • a function that references externals which have also been required,
  • a simple object with a prototype, and
  • external JS files.

To avoid issues with minification, it is necessary to explicitly specify the name of a required entity, e.g. thread.require( foo, 'foo' ).

Examples

var t = weaver.thread();

function foo(){
  return 'bar';
}

t.require( foo );

t.run(function(){
  var ret = foo();

  console.log( 't::foo() return value: ' + ret );

  broadcast( ret );
});

t.on('message', function( e ){
  var msg = e.message;
  var ret = msg;

  console.log( 'return value as heard by main JS thread/entity: ' + ret );

  t.stop();
});
thread.pass()

Pass data to the thread such that it is accessible within thread.run() etc callback functions.

thread.pass( ,passed )
  • passed

    JSON serialisable data that is passed to thread.run().

Details

This function allows for sending data to the thread. The data must be serialisable via JSON.stringify().

Examples

var t = weaver.Thread();

t.pass( { foo: 1, bar: 2 } ).run(function( data ){
  data.foo++;
  data.bar++;

  resolve(data);
}).then(function( data ){
  console.log( data );

  t1.stop();
});
thread.run()
Aliases: thread.promise(),

Run the specified function in the thread, returning a promise that is resolved when the thread calls resolve() or when the specified function returns a value.

thread.run( ,function( passed ) )
  • function( passed )

    The function which will be copied and run in the thread.

Details

Please note that the passed function to thread.run() is copied to the thread, and so it is not possible to make use of references that originate outside of the function itself. That is, a thread has its own isolated memory space.

Examples

var t = weaver.thread();

t.run(function(){
  resolve( 3 );
}).then(function( val ){
  console.log( 'resolved value: ' + val );

  t.stop();
});
thread.map()

Get a mapping from the thread using the specified mapping function that uses resolve() or a return value to specify the mapped value for each element.

thread.map( ,function( currVal, index, array ) )
  • function( currVal, index, array )

    A mapping function that specifies the resultant mapped value via resolve() or a return value.

    • currVal

      The current element being processed in the passed array.

    • index [optional]

      The index of the current element being processed in the passed array.

    • array [optional]

      The passed array map() was called upon.

Examples

var t = weaver.Thread();

t.pass([ 1, 2, 3 ]).map(function( n ){
  return n*n;
}).then(function( data ){
  console.log( data ); // [1, 4, 9]

  t1.stop();
});
thread.reduce()

Apply a function against an accumulator and each value of the passed array (from left-to-right) has to reduce it to a single value. The function specifies the resultant value via resolve() or a return value.

thread.reduce( ,function( prevVal, currVal, index, array ) [,initVal] )
  • function( prevVal, currVal, index, array )

    The accumulator function.

    • prevVal

      The value previously returned in the last invocation of the accumulator function, or initVal if supplied.

    • currVal

      The current element being processed in the passed array.

    • index

      The index of the current element being processed in the passed array.

    • array

      The passed array reduce() was called upon.

  • initVal [optional]

    Value to use as the first argument to the first call of the accumulator function.

thread.reduceRight()

Apply a function against an accumulator and each value of the passed array (from right-to-left) has to reduce it to a single value. The function specifies the resultant value via resolve() or a return value.

thread.reduceRight( ,function( prevVal, currVal, index, array ) [,initVal] )
  • function( prevVal, currVal, index, array )

    The accumulator function.

    • prevVal

      The value previously returned in the last invocation of the accumulator function, or initVal if supplied.

    • currVal

      The current element being processed in the passed array.

    • index

      The index of the current element being processed in the passed array.

    • array

      The passed array reduceRight() was called upon.

  • initVal [optional]

    Value to use as the first argument to the first call of the accumulator function.

thread.stop()
Aliases: thread.halt(), thread.terminate(),

Terminates the thread such that it no longer runs.

thread.stopped()

Get whether the thread is stopped (i.e. terminated via thread.stop()).

Events

For events of evt.type === 'message', the message itself can be found in evt.message.

thread.message()

Send the thread a message.

thread.message( ,msg )
  • msg

    The message (e.g. JSON object or string) to send to the thread.

Examples

var t = weaver.thread();

t.run(function(){
  listen(function( msg ){
      console.log( 'thread heard: ' + [msg.foo, msg.bar].join(' ') );

    broadcast( msg ); // just send it back
  });
});

t.on('message', function( e ){
  var msg = e.message;

  console.log( 'main js entity/thread heard: ' + [msg.foo, msg.bar].join(' ') );

  t.stop();
});

t.message({ foo: 'hello', bar: 'world' });
thread.on()
Aliases: thread.bind(), thread.listen(), thread.addListener(),

Bind to events that are emitted by the thread.

thread.on( ,events [,data],function(evt) )
  • events

    A space separated list of event names.

  • data [optional]

    A plain object which is passed to the handler in the event object argument.

  • function(evt)

    The handler function that is called when one of the specified events occurs.

    • evt

      The event object.

thread.on( ,eventsMap [,data] )
  • eventsMap

    A map of event names to handler functions.

  • data [optional]

    A plain object which is passed to the handler in the event object argument.

Examples

var t = weaver.thread();

t.on('run', function(){
  console.log('run');
});

t.pass([1, 2, 3]).run(function( arr ){
  return arr[0] + arr[arr.length - 1];
}).then(function( res ){
  console.log('got run response: ' + res);

  t.stop();
});
thread.promiseOn()
Aliases: thread.pon(),

Get a promise that is resolved when the first of any of the specified events is triggered on the thread.

thread.promiseOn( ,events )
  • events

    A space separated list of event names.

Examples

var thread = weaver.thread();

thread.pon('ran').then(function(){
  console.log('thread ran promise resolved');
});

thread.run(function(){
  resolve('thread has finished');
}).then(function(){
  thread.stop();
});
thread.one()

Bind to events that are emitted by the thread, and trigger the handler only once.

thread.one( ,events [,data],function(evt) )
  • events

    A space separated list of event names.

  • data [optional]

    A plain object which is passed to the handler in the event object argument.

  • function(evt)

    The handler function that is called when one of the specified events occurs.

    • evt

      The event object.

thread.one( ,eventsMap [,data] )
  • eventsMap

    A map of event names to handler functions.

  • data [optional]

    A plain object which is passed to the handler in the event object argument.

Examples

var t = weaver.thread();

t.one('run', function(){
  console.log('run (once)');
});

t.run(function(){
  return 'some response';
}).then(function( res ){
  console.log('got run x1 response: ' + res);

  return t.run(function(){
    return 'some other message';
  });
}).then(function( res ){
  console.log('got run x2 response: ' + res);

  t.stop();
});
thread.off()
Aliases: thread.unbind(), thread.unlisten(), thread.removeListener(),

Remove event handlers on the thread.

thread.off( ,events [,handler] )
  • events

    A space separated list of event names.

  • handler [optional]

    A reference to the handler function to remove.

thread.off( ,eventsMap )
  • eventsMap

    A map of event names to handler functions to remove.

Examples

var t = weaver.thread();

t.on('run', function(){
  console.log('run');
});

t.run(function(){
  return 'the first response';
}).then(function( res ){
  console.log('got run response: ' + res);

  t.off('run'); // so the 2nd one isn't triggered...
}).then(function(){
  return t.run(function(){
    return 'the second response';
  });
}).then(function(){
  t.stop();
});
thread.trigger()
Aliases: thread.emit(),

Trigger one or more events on the thread.

thread.trigger( ,events [,extraParams] )
  • events

    A space separated list of event names to trigger.

  • extraParams [optional]

    An array of additional parameters to pass to the handler.

Examples

var t = weaver.thread();

t.on('foo', function(){
  console.log('foo!');
});

t.trigger('foo');

Fabric

A fabric is a collection of threads that can be used together in a collaborative fashion for parallelism purposes, thereby increasing the overall speed of execution of parallel code. A fabric may be created as follows:

var fabric = weaver.fabric();

The new keyword and class-style uppercase naming are optional, so you may alternatively do as follows:

var fabric = new weaver.Fabric();

For most usecases, a developer would use a fabric rather than individual threads. By default, a fabric parallelises its tasks among its threads, making your code faster. A task that is not suitable to parallelism in this manner (like .reduce()) is run in a single thread of the fabric, with the fabric acting as a queue. Because multiple tasks can be run across the threads using this queuing mechanism, your code can still experience speedup.

Execution

fabric.require()
Aliases: fabric.include(),

Require a named function into each thread in the fabric, giving a global reference to the function. Plain objects or simple objects with a prototype (that can be inpected and serialised live) are also supported. Specifying the name of a JS file (i.e. a string ending in '.js') allows for importing external files into the global thread scope.

fabric.require( ,obj [,as] )
  • obj

    The named function, simple object, or JS file name to require that is serialised and copied to the fabric.

  • as [optional]

    The name of the object as available in the fabric. This is mandatory for an object that is not a named function, because its name can not be automatically inferred.

Examples

var f = weaver.fabric();

function plusplus( n ){
  return ++n;
}

f.require( plusplus ).pass([ 1, 2, 3, 4 ]).map(function( n ){
  return plusplus(n);
}).then(function( res ){
  console.log('res is ' + res);

  f.stop();
});
fabric.pass()

Pass data to the fabric such that it is accessible within fabric.spread() etc callback functions.

fabric.pass( ,passed )
  • passed

    JSON serialisable data that is passed to functions like fabric.spread().

Examples

var f = weaver.fabric();

f.pass([ 1, 2, 3, 4 ]).map(function( n ){
  return n*n;
}).then(function( res ){
  console.log('res is ' + res);

  f.stop();
});
fabric.random()

Get a random thread from the fabric.

Examples

var f = weaver.fabric();

f.random().run(function(){
  return 2 + 2;
}).then(function( sum ){
  console.log('sum should be ' + sum + ' unless the year is 1984');

  f.stop();
});
fabric.run()
Aliases: fabric.promise(),

Run the specified function in a random thread of the fabric, returning a promise that is resolved when the thread calls resolve() or when the specified function returns a value.

fabric.run( ,function( passed ) )
  • function( passed )

    The function which will be copied and run in the fabric.

Examples

var f = weaver.fabric();

f.run(function(){
  return 2 + 2;
}).then(function( sum ){
  console.log('sum should be ' + sum + ' unless the year is 1984');

  f.stop();
});
fabric.map()

Get a mapping from the fabric using the specified mapping function that uses resolve() or a return value to specify the mapped value for each element.

fabric.map( ,function( currVal, index, array ) )
  • function( currVal, index, array )

    A mapping function that specifies the resultant mapped value via resolve() or a return value.

    • currVal

      The current element being processed in the passed array.

    • index [optional]

      The index of the current element being processed in the passed array.

    • array [optional]

      The passed array map() was called upon.

Examples

var f = weaver.fabric();

f.pass([ 1, 2, 3, 4 ]).map(function( n ){
  return n*n;
}).then(function( res ){
  console.log('res is ' + res);

  f.stop();
});
fabric.filter()

Filters the passed array, giving a resultant array that contains the elements which pass the specified test function. The test function returns or resolve()s to specify the test result.

fabric.filter( ,function( currVal, index, array ) )
  • function( currVal, index, array )

    The test function that returns or resolve()s a truthy value to specify whether the specified value passes the test.

    • currVal

      The current element being processed in the passed array.

    • index [optional]

      The index of the current element being processed in the passed array.

    • array [optional]

      The passed array filter() was called upon.

Examples

var f = weaver.fabric();

f.pass([ -2, -1, 0, 1, 2 ]).filter(function( n ){
  return n > 0;
}).then(function( res ){
  console.log('res is ' + res);

  f.stop();
});
fabric.reduce()

Apply a function against an accumulator and each value of the passed array (from left-to-right) has to reduce it to a single value. The function specifies the resultant value via resolve() or a return value.

fabric.reduce( ,function( prevVal, currVal, index, array ) [,initVal] )
  • function( prevVal, currVal, index, array )

    The accumulator function.

    • prevVal

      The value previously returned in the last invocation of the accumulator function, or initVal if supplied.

    • currVal

      The current element being processed in the passed array.

    • index

      The index of the current element being processed in the passed array.

    • array

      The passed array reduce() was called upon.

  • initVal [optional]

    Value to use as the first argument to the first call of the accumulator function.

Examples

var f = weaver.fabric();

f.pass([ 1, 2, 3, 4 ]).reduce(function( prev, curr ){
  return prev + curr;
}).then(function( res ){
  console.log('res is ' + res);

  f.stop();
});
fabric.reduceRight()

Apply a function against an accumulator and each value of the passed array (from right-to-left) has to reduce it to a single value. The function specifies the resultant value via resolve() or a return value.

fabric.reduceRight( ,function( prevVal, currVal, index, array ) [,initVal] )
  • function( prevVal, currVal, index, array )

    The accumulator function.

    • prevVal

      The value previously returned in the last invocation of the accumulator function, or initVal if supplied.

    • currVal

      The current element being processed in the passed array.

    • index

      The index of the current element being processed in the passed array.

    • array

      The passed array reduceRight() was called upon.

  • initVal [optional]

    Value to use as the first argument to the first call of the accumulator function.

Examples

var f = weaver.fabric();

f.pass([ 1, 2, 3, 4 ]).reduceRight(function( prev, curr ){
  return prev - curr;
}).then(function( res ){
  console.log('res is ' + res);

  f.stop();
});
fabric.sort()

Sort the passed array, using a divide and conquer strategy with the threads.

fabric.sort( [,function( a, b )] )
  • function( a, b ) [optional]

    The sorting comparison function that returns a negative value for a before b, zero for a the same as b, and a positive value for a after b.

    • a

      The first value to compare.

    • b

      The second value to compare.

Examples

var f = weaver.fabric();

f.pass([ 4, 1, 2, 5, 3 ]).sort().then(function( res ){
  console.log('res is ' + res);

  f.stop();
});
fabric.spread()

Split the passed data into slices to spread the data equally among the threads of the fabric. The passed processing function specifies the resultant array slice via a return value or resolve().

fabric.spread( ,function( slice ) )
  • function( slice )

    The processing function which is run on each slice of passed data.

    • slice

      An array containing a slice of the passed data.

Examples

var f = weaver.fabric();

f.pass([ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]).spread(function( slice ){
  var res = [];

  for( var i = 0; i < slice.length; i++ ){
    res.push( slice[i] * slice[i] );
  }

  return res;
}).then(function( res ){
  console.log('res is ' + res);

  f.stop();
});
fabric.stop()
Aliases: fabric.halt(), fabric.terminate(),

Terminates the fabric such that all its threads no longer run.

Examples

var f = weaver.fabric();

f.run(function(){
  return 2 + 2;
}).then(function( sum ){
  console.log('sum should be ' + sum + ' unless the year is 1984');

  f.stop();
});

Events

fabric.message()

Send a random thread in the fabric a message.

fabric.message( ,msg )
  • msg

    The message (e.g. JSON object or string) to send to the thread.

fabric.broadcast()

Send all threads in the fabric a message.

fabric.broadcast( ,msg )
  • msg

    The message (e.g. JSON object or string) to send to the threads.

fabric.on()
Aliases: fabric.bind(), fabric.listen(), fabric.addListener(),

Bind to events that are emitted by the fabric.

fabric.on( ,events [,data],function(evt) )
  • events

    A space separated list of event names.

  • data [optional]

    A plain object which is passed to the handler in the event object argument.

  • function(evt)

    The handler function that is called when one of the specified events occurs.

    • evt

      The event object.

fabric.on( ,eventsMap [,data] )
  • eventsMap

    A map of event names to handler functions.

  • data [optional]

    A plain object which is passed to the handler in the event object argument.

fabric.promiseOn()
Aliases: fabric.pon(),

Get a promise that is resolved when the first of any of the specified events is triggered on the fabric.

fabric.promiseOn( ,events )
  • events

    A space separated list of event names.

fabric.one()

Bind to events that are emitted by the fabric, and trigger the handler only once.

fabric.one( ,events [,data],function(evt) )
  • events

    A space separated list of event names.

  • data [optional]

    A plain object which is passed to the handler in the event object argument.

  • function(evt)

    The handler function that is called when one of the specified events occurs.

    • evt

      The event object.

fabric.one( ,eventsMap [,data] )
  • eventsMap

    A map of event names to handler functions.

  • data [optional]

    A plain object which is passed to the handler in the event object argument.

fabric.off()
Aliases: fabric.unbind(), fabric.unlisten(), fabric.removeListener(),

Remove event handlers on the fabric.

fabric.off( ,events [,handler] )
  • events

    A space separated list of event names.

  • handler [optional]

    A reference to the handler function to remove.

fabric.off( ,eventsMap )
  • eventsMap

    A map of event names to handler functions to remove.

fabric.trigger()
Aliases: fabric.emit(),

Trigger one or more events on the fabric.

fabric.trigger( ,events [,extraParams] )
  • events

    A space separated list of event names to trigger.

  • extraParams [optional]

    An array of additional parameters to pass to the handler.

Console
foo bar baz TODO