mirror of
https://github.com/status-im/consul.git
synced 2025-01-10 05:45:46 +00:00
01d1b3c139
1. EventSources now pass themselves thorugh to the run function as a second argument. This enables the use of arrow functions along with the EventSources API `(configuration, source) => source.close()`. Order of arguments could potentially be switched at a later date. 2. BlockingEventSources now let you pass an 'event' through at instantation time. If you do this, the event will immediately be dispatched once the EventSource is opened. The usecase for this is for 'unfreezing' cached BlockingEvents. This makes it easier to provide a cache for BlockingEventSources by caching its data rather than the entire BlockingEventSource itself. ``` new BlockingEventSource( (config, source) => { /* something */ }, { cursor: 1024, // this would also come from a cache currentEvent: getFromSomeSortOfCache(eventSourceId) //this is the new bit } ); // more realistically new BlockingEventSource( (config, source) => { return data.findSomething(slug, config) }, getFromSomeSortOfCache(eventSourceId) ); ```
82 lines
2.2 KiB
JavaScript
82 lines
2.2 KiB
JavaScript
export const defaultRunner = function(target, configuration, isClosed) {
|
|
if (isClosed(target)) {
|
|
target.dispatchEvent({ type: 'close' });
|
|
return;
|
|
}
|
|
// TODO Consider wrapping this is a promise for none thenable returns
|
|
return target.source
|
|
.bind(target)(configuration, target)
|
|
.then(function(res) {
|
|
return defaultRunner(target, configuration, isClosed);
|
|
});
|
|
};
|
|
const errorEvent = function(e) {
|
|
return new ErrorEvent('error', {
|
|
error: e,
|
|
message: e.message,
|
|
});
|
|
};
|
|
const isClosed = function(target) {
|
|
switch (target.readyState) {
|
|
case 2: // CLOSED
|
|
case 3: // CLOSING
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
export default function(
|
|
EventTarget,
|
|
P = Promise,
|
|
run = defaultRunner,
|
|
createErrorEvent = errorEvent
|
|
) {
|
|
return class extends EventTarget {
|
|
constructor(source, configuration = {}) {
|
|
super();
|
|
this.readyState = 2;
|
|
this.source =
|
|
typeof source !== 'function'
|
|
? function(configuration, target) {
|
|
this.close();
|
|
return P.resolve();
|
|
}
|
|
: source;
|
|
this.readyState = 0; // CONNECTING
|
|
P.resolve()
|
|
.then(() => {
|
|
// if we are already closed, don't do anything
|
|
if (this.readyState > 1) {
|
|
return;
|
|
}
|
|
this.readyState = 1; // open
|
|
// the connection _was just_ opened
|
|
this.dispatchEvent({ type: 'open' });
|
|
return run(this, configuration, isClosed);
|
|
})
|
|
.catch(e => {
|
|
this.dispatchEvent(createErrorEvent(e));
|
|
// close after the dispatch so we can tell if it was an error whilst closed or not
|
|
// but make sure its before the promise tick
|
|
this.readyState = 2; // CLOSE
|
|
})
|
|
.then(() => {
|
|
// This only gets called when the promise chain completely finishes
|
|
// so only when its completely closed.
|
|
this.readyState = 2; // CLOSE
|
|
});
|
|
}
|
|
close() {
|
|
// additional readyState 3 = CLOSING
|
|
switch (this.readyState) {
|
|
case 2: // CLOSED
|
|
// it's already CLOSED , do nothing
|
|
break;
|
|
default:
|
|
this.readyState = 3; // CLOSING
|
|
}
|
|
// non-standard
|
|
return this;
|
|
}
|
|
};
|
|
}
|