rafa
Version:
Rafa.js is a Javascript framework for building concurrent applications.
164 lines (142 loc) • 4.78 kB
JavaScript
// The Rafa object has a duel role: it is exposed as the top level object
// in the library (returned from require), and all objects in the Rafa
// framework inherit the Rafa object within its prototype chain. The latter
// provides efficient access to common functions without the need to find
// references in closures.
//
// The bind functions bind an object context to a function. Each bind
// function has a two digit suffix where the first digit represents how
// many arguments will be partially applied and the second digit represents
// how many arguments the returned function will expose.
//
const Rafa = {
noop,
identity,
extend,
contextid,
Message,
ErrorMessage,
ErrorDoneMessage,
DoneMessage,
RingBuffer,
Channel,
Enumerator,
Context,
Stream,
Property,
// Future is an object that creates a new Promise object and exposes it along
// with the resolve and reject functions associated with the Promise. This
// is a convenience for a common pattern.
Future() {
let resolve, reject;
this.promise = new Promise((a, b) => { resolve = a; reject = b; });
this.resolve = resolve;
this.reject = reject;
},
// Variable argument binder. Return a new function that
// executes `fn` with `this` set to `obj`. The function `fn` accepts
// a variable number of arguments. This function is not as efficient as
// calling the specific bind functions below.
// `(a,b) => ((c...) => b.apply(a, c))`
bind(obj, fn) {
return function() {
const len = arguments.length;
const args = new Array(len);
for (let i = 0; i < len; i++) {
args[i] = arguments[i];
}
return fn.apply(obj, args);
};
},
// Zero argument binder. Return a new function that executes `fn` with `this`
// set to `obj`. The function `fn` accepts no arguments.
// `(a,b) => (=> b.call(a))`
bind00(obj, fn) {
return function() { return fn.call(obj); };
},
// One argument binder. Return a new function that executes `fn` with `this`
// set to `obj`. The function `fn` accepts one argument.
// `(a,b) => (c => b.call(a,c))`
bind10(obj, fn) {
return function(c) { return fn.call(obj, c); };
},
// Partial application binder. Return a new function that executes `fn`
// with `this` set to `obj` and the first argument bound to `arg0`. The
// function `fn` accepts two arguments and the returned function accepts
// one.
// `(a,b,c) => (d => b.call(a,c,d))`
bind11(obj, fn, arg0) {
return function(arg1) { return fn.call(obj, arg0, arg1); };
},
buffer(capacity, overwrite) {
return new this.RingBuffer(capacity, overwrite);
},
// Create a new Listener object.
channel(size, action) {
return new this.Channel(size, action);
},
// Create a new Context object.
context(done) {
return new this.Context(done);
},
// Create a new channel that is written to after `delay` milliseconds.
// The value written is a `Date` object. The channel does not have a buffer.
defer(delay) {
const channel = this.channel();
setTimeout(() => channel.write(new Date()), delay);
return channel;
},
// Create a new DoneMessage object.
doneMessage(value) {
return new this.DoneMessage(value);
},
// Create a new ErrorMessage object.
errorMessage(value) {
return new this.ErrorMessage(value);
},
errordoneMessage(error) {
return new this.ErrorDoneMessage(error);
},
// Create a new Future object.
future() {
return new this.Future();
},
// Create a new channel that is written to every `delay` milliseconds.
// The value written is a `Date` object. Closing the channel stops the
// interval timer. THe channel has a buffer capacity of 1.
interval(delay) {
const channel = this.channel(1, "rotate");
const next = () => {
if (channel.closed()) clearInterval(id);
else channel.write(new Date());
};
let id = setInterval(next, delay);
return channel;
},
// Create a new Message object.
message(value) {
return new this.Message(value);
},
// Return a function that accepts a variable number of arguments. When
// called, the arguments are transformed to an Array and passed to a
// callback function. `params(callback: Array => A): ((...args) => A)`
params(callback) {
return function() {
const len = arguments.length;
const params = new Array(len);
for (let i = 0; i < len; i++)
params[i] = arguments[i];
return callback(params);
};
},
property(set) {
return new this.Property(set);
},
slice(arraylike, index, end) {
return Array.prototype.slice.call(arraylike, index, end);
},
// Create a new Stream object.
stream() {
return new this.Stream();
}
};