Skip to content

Instantly share code, notes, and snippets.

@jaz303
Last active August 29, 2015 14:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jaz303/d56ee88acf652ca79bf7 to your computer and use it in GitHub Desktop.
Save jaz303/d56ee88acf652ca79bf7 to your computer and use it in GitHub Desktop.
Go-style channels in Javascript with promises/generators
//
// Lame implementation of a channel
function channel() {
return new Channel();
}
function Channel() {
this._queue = [];
this._waiters = [];
}
Channel.prototype.take = function() {
var _resolve = null;
var promise = new Promise(function(resolve, reject) {
_resolve = resolve;
});
promise.resolve = _resolve;
this._waiters.push(promise);
this._drain();
return promise;
}
Channel.prototype.put = function(item) {
this._queue.push(item);
this._drain();
}
Channel.prototype._drain = function() {
if (this._drainRequested) return;
this._drainRequested = true;
var self = this;
setTimeout(function() {
self._drainRequested = false;
while (self._queue.length && self._waiters.length) {
self._waiters.shift().resolve(self._queue.shift());
}
}, 0);
}
//
//
function wait(delay) {
return new Promise(function(resolve) {
setTimeout(resolve, delay)
});
}
function engine() {
var tasks = [];
var waiting = [];
function spawn(fn, args, ctx) {
tasks.push([fn.apply(ctx || null, args), undefined]);
tick();
}
function tick() {
var task = tasks.shift();
var result = task[0].next(task[1]);
if (result.done) {
// do nothing, task complete
} else if (result.value && typeof result.value.then === 'function') {
result.value.then(function(res) {
tasks.push([task[0], res]);
tick();
});
} else {
tasks.push(task);
process.nextTick(tick);
}
}
return spawn;
}
var spawn = engine();
var ch = channel();
spawn(function *() {
while (true) {
yield wait(Math.random() * 1000);
var num = Math.floor(Math.random() * 10);
for (var i = 0; i < num; ++i) {
var val = Math.floor(Math.random() * 10);
console.log("put: " + val);
ch.put(val);
}
}
});
for (var i = 0; i < 10; ++i) {
spawn(function *(id) {
while (true) {
var val = yield ch.take();
console.log("[id=" + id + "] take: " + val);
}
}, [i]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment