UNPKG

fluture

Version:

FantasyLand compliant (monadic) alternative to Promises

124 lines (104 loc) 3.23 kB
import {noop} from './internal/utils.js'; import {createInterpreter, application1, future} from './future.js'; export var Cold = 0; export var Pending = 1; export var Crashed = 2; export var Rejected = 3; export var Resolved = 4; export function Queued(rec, rej, res){ this[Crashed] = rec; this[Rejected] = rej; this[Resolved] = res; } export var Cache = createInterpreter(1, 'cache', function Cache$interpret(rec, rej, res){ var cancel = noop; switch(this._state){ /* c8 ignore next 4 */ case Pending: cancel = this._addToQueue(rec, rej, res); break; case Crashed: rec(this._value); break; case Rejected: rej(this._value); break; case Resolved: res(this._value); break; default: this._queue = []; cancel = this._addToQueue(rec, rej, res); this.run(); } return cancel; }); Cache.prototype._cancel = noop; Cache.prototype._queue = null; Cache.prototype._queued = 0; Cache.prototype._value = undefined; Cache.prototype._state = Cold; Cache.prototype.extractLeft = function Cache$extractLeft(){ return this._state === Rejected ? [this._value] : []; }; Cache.prototype.extractRight = function Cache$extractRight(){ return this._state === Resolved ? [this._value] : []; }; Cache.prototype._addToQueue = function Cache$addToQueue(rec, rej, res){ var _this = this; if(_this._state > Pending) return noop; var i = _this._queue.push(new Queued(rec, rej, res)) - 1; _this._queued = _this._queued + 1; return function Cache$removeFromQueue(){ if(_this._state > Pending) return; _this._queue[i] = undefined; _this._queued = _this._queued - 1; if(_this._queued === 0) _this.reset(); }; }; Cache.prototype._drainQueue = function Cache$drainQueue(){ if(this._state <= Pending) return; if(this._queued === 0) return; var queue = this._queue; var length = queue.length; var state = this._state; var value = this._value; for(var i = 0; i < length; i++){ queue[i] && queue[i][state](value); queue[i] = undefined; } this._queue = undefined; this._queued = 0; }; Cache.prototype.crash = function Cache$crash(error){ if(this._state > Pending) return; this._value = error; this._state = Crashed; this._drainQueue(); }; Cache.prototype.reject = function Cache$reject(reason){ if(this._state > Pending) return; this._value = reason; this._state = Rejected; this._drainQueue(); }; Cache.prototype.resolve = function Cache$resolve(value){ if(this._state > Pending) return; this._value = value; this._state = Resolved; this._drainQueue(); }; Cache.prototype.run = function Cache$run(){ var _this = this; if(_this._state > Cold) return; _this._state = Pending; _this._cancel = _this.$1._interpret( function Cache$fork$rec(x){ _this.crash(x) }, function Cache$fork$rej(x){ _this.reject(x) }, function Cache$fork$res(x){ _this.resolve(x) } ); }; Cache.prototype.reset = function Cache$reset(){ if(this._state === Cold) return; if(this._state === Pending) this._cancel(); this._cancel = noop; this._queue = []; this._queued = 0; this._value = undefined; this._state = Cold; }; export function cache(m){ return new Cache(application1(cache, future, arguments), m); }