Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
123 lines
3.1 KiB
JavaScript
123 lines
3.1 KiB
JavaScript
/* global Process */
|
|
|
|
'use strict';
|
|
|
|
/**
|
|
* Combine the abilities of the event handling and asynchronous operations
|
|
* sequentializing together. So that every Stream could:
|
|
*
|
|
* 1. For the ordinary events, append steps to the main Process to queue
|
|
* the event handlers.
|
|
* 2. For other urgent events (interrupts), immediately execute the event
|
|
* handler without queuing it.
|
|
* 3. Only receive events when it's 'ready'. Before that, no source events
|
|
* would be forwarded and handled.
|
|
* 4. Once phase becomes 'stop', no events would be received again.
|
|
**/
|
|
(function(exports) {
|
|
var Stream = function(configs) {
|
|
this.configs = {
|
|
events: configs.events || [],
|
|
interrupts: configs.interrupts || []
|
|
};
|
|
if (configs.sources && 0 !== configs.sources.length) {
|
|
this.configs.sources = configs.sources;
|
|
} else {
|
|
this.configs.sources = [];
|
|
}
|
|
this._forwardTo = null;
|
|
// Need to delegate to Source.
|
|
this.onchange = this.onchange.bind(this);
|
|
};
|
|
|
|
Stream.prototype.phase = function() {
|
|
return this.process.states.phase;
|
|
};
|
|
|
|
Stream.prototype.start = function(forwardTo) {
|
|
this._forwardTo = forwardTo;
|
|
this.process = new Process();
|
|
this.process.start();
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Kick off Source and start do things.
|
|
*/
|
|
Stream.prototype.ready = function() {
|
|
this.configs.sources.forEach((source) => {
|
|
source.start(this.onchange);
|
|
});
|
|
return this;
|
|
};
|
|
|
|
Stream.prototype.stop = function() {
|
|
this.process.stop();
|
|
this.configs.sources.forEach((source) => {
|
|
source.stop();
|
|
});
|
|
return this;
|
|
};
|
|
|
|
Stream.prototype.destroy = function() {
|
|
this.process.destroy();
|
|
return this;
|
|
};
|
|
|
|
Stream.prototype.next = function(step) {
|
|
this.process.next(step);
|
|
return this;
|
|
};
|
|
|
|
Stream.prototype.rescue = function(rescuer) {
|
|
this.process.rescue(rescuer);
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Return a Promise get resolved when the stream turn to
|
|
* the specific phase. For example:
|
|
*
|
|
* stream.until('stop')
|
|
* .then(() => { console.log('stream stopped') });
|
|
* stream.start();
|
|
*/
|
|
Stream.prototype.until = function(phase) {
|
|
return this.process.until(phase);
|
|
};
|
|
|
|
/**
|
|
* Only when all tasks passed in get resolved,
|
|
* the process would go to the next.
|
|
*/
|
|
Stream.prototype.wait = function(tasks) {
|
|
this.process.wait(tasks);
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* It would receive events from Source, and than queue or not queue
|
|
* it, depends on whether the event is an interrupt.
|
|
*/
|
|
Stream.prototype.onchange = function(evt) {
|
|
if ('start' !== this.process.states.phase) {
|
|
return this;
|
|
}
|
|
if (-1 !== this.configs.interrupts.indexOf(evt.type)) {
|
|
// Interrupt would be handled immediately.
|
|
this._forwardTo(evt);
|
|
return this;
|
|
} else {
|
|
// Event would be handled after queuing.
|
|
// This is, if the event handle return a Promise or Process,
|
|
// that can be fulfilled later.
|
|
this.process.next(() => {
|
|
return this._forwardTo(evt);
|
|
});
|
|
return this;
|
|
}
|
|
};
|
|
|
|
exports.Stream = Stream;
|
|
})(window);
|
|
|