csf
Version:
Generator based flow control with context providing
117 lines (96 loc) • 2.38 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.DONE = undefined;
exports.default = channel;
var _constants = require("./constants");
var DONE = exports.DONE = Symbol("DONE");
function channel() {
var sequence = [];
var cancelled = false;
var done = false;
var final = void 0;
var anticipant = void 0;
var channelEmitter = function channelEmitter() {
if (cancelled) {
// Return undefined intead of promise
return undefined;
}
if (sequence.length) {
return Promise.resolve(sequence.shift());
} else if (done) {
cancelled = true;
return Promise.resolve(final);
}
return new Promise(function (resolve) {
anticipant = resolve;
});
};
channelEmitter[_constants.CHANNEL] = true;
/*
* Immediately permanently disable channel
*/
channelEmitter[_constants.CANCEL] = function () {
cancelled = true;
};
/*
* Because createChannel is not a part of fx,
* returned function should not have payload flag
*/
// channelEmitter[PAYLOAD] = true;
/*
* Complete channel, disable push, resolve active promise with undefined
* or specified final value
*/
channelEmitter.done = function (finalValue) {
done = true;
if (anticipant) {
anticipant(final);
} else {
final = finalValue;
}
};
channelEmitter.push = function (next, last) {
if (done) {
return;
}
if (cancelled) {
throw new Error("Pushing to cancelled channel is unreachable");
}
if (last) {
// Force done channel
channelEmitter.done(next);
} else {
if (anticipant) {
anticipant(next);
anticipant = null;
} else {
sequence.push(next);
}
if (sequence.length > 1000) {
throw new Error("Dangerously count of observable result");
}
}
};
channelEmitter.next = function () {
var nextPromise = channelEmitter.apply(undefined, arguments);
if (nextPromise) {
return nextPromise.then(function (value) {
return {
value: value,
done: false
};
});
}
return Promise.resolve({
done: true,
value: undefined
});
};
/* Return count of cached values */
channelEmitter.count = function () {
return sequence.length;
};
return channelEmitter;
}