Skip to content

Commit

Permalink
convert most util classes to ES6 class syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
mourner committed Oct 19, 2016
1 parent 4e1d93c commit e7df00f
Show file tree
Hide file tree
Showing 6 changed files with 239 additions and 228 deletions.
130 changes: 66 additions & 64 deletions js/util/actor.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
'use strict';

module.exports = Actor;

/**
* An implementation of the [Actor design pattern](http://en.wikipedia.org/wiki/Actor_model)
* that maintains the relationship between asynchronous tasks and the objects
Expand All @@ -13,74 +11,78 @@ module.exports = Actor;
* @param {string|number} mapId A unique identifier for the Map instance using this Actor.
* @private
*/
function Actor(target, parent, mapId) {
this.target = target;
this.parent = parent;
this.mapId = mapId;
this.callbacks = {};
this.callbackID = 0;
this.receive = this.receive.bind(this);
this.target.addEventListener('message', this.receive, false);
}

/**
* Sends a message from a main-thread map to a Worker or from a Worker back to
* a main-thread map instance.
*
* @param {string} type The name of the target method to invoke or '[source-type].name' for a method on a WorkerSource.
* @param {object} data
* @param {Function} [callback]
* @param {Array} [buffers] A list of buffers to "transfer" (see https://developer.mozilla.org/en-US/docs/Web/API/Transferable)
* @param {string} [targetMapId] A particular mapId to which to send this message.
* @private
*/
Actor.prototype.send = function(type, data, callback, buffers, targetMapId) {
const id = callback ? `${this.mapId}:${this.callbackID++}` : null;
if (callback) this.callbacks[id] = callback;
this.target.postMessage({
targetMapId: targetMapId,
sourceMapId: this.mapId,
type: type,
id: String(id),
data: data
}, buffers);
};

Actor.prototype.receive = function(message) {
const data = message.data,
id = data.id;
let callback;

if (data.targetMapId && this.mapId !== data.targetMapId)
return;

if (data.type === '<response>') {
callback = this.callbacks[data.id];
delete this.callbacks[data.id];
if (callback) callback(data.error || null, data.data);
} else if (typeof data.id !== 'undefined' && this.parent[data.type]) {
// data.type == 'load tile', 'remove tile', etc.
this.parent[data.type](data.sourceMapId, data.data, done.bind(this));
} else if (typeof data.id !== 'undefined' && this.parent.getWorkerSource) {
// data.type == sourcetype.method
const keys = data.type.split('.');
const workerSource = this.parent.getWorkerSource(data.sourceMapId, keys[0]);
workerSource[keys[1]](data.data, done.bind(this));
} else {
this.parent[data.type](data.data);
class Actor {
constructor(target, parent, mapId) {
this.target = target;
this.parent = parent;
this.mapId = mapId;
this.callbacks = {};
this.callbackID = 0;
this.receive = this.receive.bind(this);
this.target.addEventListener('message', this.receive, false);
}

function done(err, data, buffers) {
/**
* Sends a message from a main-thread map to a Worker or from a Worker back to
* a main-thread map instance.
*
* @param {string} type The name of the target method to invoke or '[source-type].name' for a method on a WorkerSource.
* @param {object} data
* @param {Function} [callback]
* @param {Array} [buffers] A list of buffers to "transfer" (see https://developer.mozilla.org/en-US/docs/Web/API/Transferable)
* @param {string} [targetMapId] A particular mapId to which to send this message.
* @private
*/
send(type, data, callback, buffers, targetMapId) {
const id = callback ? `${this.mapId}:${this.callbackID++}` : null;
if (callback) this.callbacks[id] = callback;
this.target.postMessage({
targetMapId: targetMapId,
sourceMapId: this.mapId,
type: '<response>',
type: type,
id: String(id),
error: err ? String(err) : null,
data: data
}, buffers);
}
};

Actor.prototype.remove = function () {
this.target.removeEventListener('message', this.receive, false);
};
receive(message) {
const data = message.data,
id = data.id;
let callback;

if (data.targetMapId && this.mapId !== data.targetMapId)
return;

const done = (err, data, buffers) => {
this.target.postMessage({
sourceMapId: this.mapId,
type: '<response>',
id: String(id),
error: err ? String(err) : null,
data: data
}, buffers);
};

if (data.type === '<response>') {
callback = this.callbacks[data.id];
delete this.callbacks[data.id];
if (callback) callback(data.error || null, data.data);
} else if (typeof data.id !== 'undefined' && this.parent[data.type]) {
// data.type == 'load tile', 'remove tile', etc.
this.parent[data.type](data.sourceMapId, data.data, done);
} else if (typeof data.id !== 'undefined' && this.parent.getWorkerSource) {
// data.type == sourcetype.method
const keys = data.type.split('.');
const workerSource = this.parent.getWorkerSource(data.sourceMapId, keys[0]);
workerSource[keys[1]](data.data, done);
} else {
this.parent[data.type](data.data);
}
}

remove() {
this.target.removeEventListener('message', this.receive, false);
}
}

module.exports = Actor;
37 changes: 20 additions & 17 deletions js/util/dictionary_coder.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,27 @@

const assert = require('assert');

module.exports = DictionaryCoder;
class DictionaryCoder {

function DictionaryCoder(strings) {
this._stringToNumber = {};
this._numberToString = [];
for (let i = 0; i < strings.length; i++) {
const string = strings[i];
this._stringToNumber[string] = i;
this._numberToString[i] = string;
constructor(strings) {
this._stringToNumber = {};
this._numberToString = [];
for (let i = 0; i < strings.length; i++) {
const string = strings[i];
this._stringToNumber[string] = i;
this._numberToString[i] = string;
}
}
}

DictionaryCoder.prototype.encode = function(string) {
assert(string in this._stringToNumber);
return this._stringToNumber[string];
};
encode(string) {
assert(string in this._stringToNumber);
return this._stringToNumber[string];
}

DictionaryCoder.prototype.decode = function(n) {
assert(n < this._numberToString.length);
return this._numberToString[n];
};
decode(n) {
assert(n < this._numberToString.length);
return this._numberToString[n];
}
}

module.exports = DictionaryCoder;
42 changes: 21 additions & 21 deletions js/util/dispatcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,29 @@
const util = require('./util');
const Actor = require('./actor');

module.exports = Dispatcher;

/**
* Responsible for sending messages from a {@link Source} to an associated
* {@link WorkerSource}.
*
* @interface Dispatcher
* @private
*/
function Dispatcher(workerPool, parent) {
this.workerPool = workerPool;
this.actors = [];
this.currentActor = 0;
this.id = util.uniqueId();
const workers = this.workerPool.acquire(this.id);
for (let i = 0; i < workers.length; i++) {
const worker = workers[i];
const actor = new Actor(worker, parent, this.id);
actor.name = `Worker ${i}`;
this.actors.push(actor);
class Dispatcher {

constructor(workerPool, parent) {
this.workerPool = workerPool;
this.actors = [];
this.currentActor = 0;
this.id = util.uniqueId();
const workers = this.workerPool.acquire(this.id);
for (let i = 0; i < workers.length; i++) {
const worker = workers[i];
const actor = new Actor(worker, parent, this.id);
actor.name = `Worker ${i}`;
this.actors.push(actor);
}
}
}

Dispatcher.prototype = {
/**
* Broadcast a message to all Workers.
* @method
Expand All @@ -37,12 +36,12 @@ Dispatcher.prototype = {
* @memberof Dispatcher
* @instance
*/
broadcast: function(type, data, cb) {
broadcast(type, data, cb) {
cb = cb || function () {};
util.asyncAll(this.actors, (actor, done) => {
actor.send(type, data, done);
}, cb);
},
}

/**
* Send a message to a Worker.
Expand All @@ -56,20 +55,21 @@ Dispatcher.prototype = {
* @memberof Dispatcher
* @instance
*/
send: function(type, data, callback, targetID, buffers) {
send(type, data, callback, targetID, buffers) {
if (typeof targetID !== 'number' || isNaN(targetID)) {
// Use round robin to send requests to web workers.
targetID = this.currentActor = (this.currentActor + 1) % this.actors.length;
}

this.actors[targetID].send(type, data, callback, buffers);
return targetID;
},
}

remove: function() {
remove() {
this.actors.forEach((actor) => { actor.remove(); });
this.actors = [];
this.workerPool.release(this.id);
}
};
}

module.exports = Dispatcher;
Loading

0 comments on commit e7df00f

Please sign in to comment.