2019-04-28 23:45:03 -05:00
|
|
|
import {compose, EventEmitter, TickingPromise} from '@avocado/core';
|
2019-03-17 23:45:48 -05:00
|
|
|
|
|
|
|
import {Traversal} from './traversal';
|
|
|
|
import {Traversals} from './traversals';
|
|
|
|
|
2019-04-08 17:41:20 -05:00
|
|
|
const decorate = compose(
|
|
|
|
EventEmitter,
|
|
|
|
);
|
|
|
|
|
|
|
|
export class Actions extends decorate(Traversals) {
|
2019-03-17 23:45:48 -05:00
|
|
|
|
2019-05-05 04:26:35 -05:00
|
|
|
static type() {
|
|
|
|
return 'actions';
|
|
|
|
}
|
|
|
|
|
2019-03-17 23:45:48 -05:00
|
|
|
constructor() {
|
|
|
|
super();
|
2019-04-07 12:00:11 -05:00
|
|
|
this._index = 0;
|
2019-03-17 23:45:48 -05:00
|
|
|
this.pending = null;
|
|
|
|
}
|
|
|
|
|
2019-04-23 00:30:44 -05:00
|
|
|
emitFinished() {
|
|
|
|
this.emit('actionsFinished');
|
2019-04-20 16:02:52 -05:00
|
|
|
}
|
|
|
|
|
2019-03-17 23:45:48 -05:00
|
|
|
get index() {
|
2019-04-07 12:00:11 -05:00
|
|
|
return this._index;
|
2019-03-17 23:45:48 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
set index(index) {
|
2019-04-07 12:00:11 -05:00
|
|
|
this._index = index;
|
2019-03-17 23:45:48 -05:00
|
|
|
}
|
|
|
|
|
2019-06-06 00:09:51 -05:00
|
|
|
get() {
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2019-03-17 23:45:48 -05:00
|
|
|
tick(context, elapsed) {
|
|
|
|
if (this.traversals.length === 0) {
|
2019-04-23 00:30:44 -05:00
|
|
|
this.emitFinished();
|
2019-03-17 23:45:48 -05:00
|
|
|
return;
|
|
|
|
}
|
2019-05-27 21:51:39 -05:00
|
|
|
if (this.pending) {
|
|
|
|
if (
|
|
|
|
this.pending instanceof TickingPromise
|
|
|
|
&& 'function' === typeof this.pending.ticker
|
|
|
|
) {
|
|
|
|
this.pending.ticker(elapsed);
|
|
|
|
}
|
2019-03-17 23:45:48 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Actions execute immediately until a promise is made, or they're all
|
|
|
|
// executed.
|
|
|
|
while (true) {
|
|
|
|
const result = this.traversals[this.index].traverse(context);
|
|
|
|
if (result instanceof Promise) {
|
2019-05-27 21:51:39 -05:00
|
|
|
result.then(() => {
|
|
|
|
this.prologue();
|
|
|
|
});
|
2019-03-17 23:45:48 -05:00
|
|
|
result.catch((error) => {
|
2019-05-27 21:51:39 -05:00
|
|
|
console.error(error);
|
|
|
|
this.prologue();
|
2019-03-17 23:45:48 -05:00
|
|
|
});
|
|
|
|
this.pending = result;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
this.prologue();
|
|
|
|
if (0 === this.index) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-06 00:09:51 -05:00
|
|
|
parallel(context) {
|
|
|
|
const promises = [];
|
|
|
|
const results = [];
|
|
|
|
const tickingPromises = [];
|
|
|
|
for (let i = 0; i < this.traversals.length; i++) {
|
|
|
|
const traversal = this.traversals[i];
|
|
|
|
const result = traversal.traverse(context);
|
|
|
|
results.push(result);
|
|
|
|
if (result instanceof TickingPromise) {
|
|
|
|
tickingPromises.push(result);
|
2019-06-07 00:14:06 -05:00
|
|
|
result.then(() => {
|
|
|
|
tickingPromises.splice(tickingPromises.indexOf(result), 1);
|
|
|
|
});
|
2019-06-06 00:09:51 -05:00
|
|
|
}
|
|
|
|
else if (result instanceof Promise) {
|
|
|
|
promises.push(result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (tickingPromises.length > 0) {
|
|
|
|
const tickingPromise = new TickingPromise((resolve) => {
|
|
|
|
resolve(Promise.all(results));
|
|
|
|
});
|
|
|
|
tickingPromise.ticker = (elapsed) => {
|
|
|
|
for (let i = 0; i < tickingPromises.length; i++) {
|
|
|
|
tickingPromises[i].ticker(elapsed);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
return tickingPromise;
|
|
|
|
}
|
|
|
|
if (promises.length > 0) {
|
|
|
|
return Promise.all(results);
|
|
|
|
}
|
|
|
|
return results;
|
|
|
|
}
|
|
|
|
|
2019-03-17 23:45:48 -05:00
|
|
|
prologue() {
|
|
|
|
this.pending = null;
|
2019-04-09 09:39:00 -05:00
|
|
|
if (0 === (this.index = (this.index + 1) % this.traversals.length)) {
|
2019-04-23 00:30:44 -05:00
|
|
|
this.emitFinished();
|
2019-03-17 23:45:48 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-07 00:14:16 -05:00
|
|
|
serial(context) {
|
|
|
|
// Do a "dry" tick.
|
|
|
|
this.tick(context, 0);
|
|
|
|
// If it's pending, we have to return a ticking promise.
|
|
|
|
if (this.pending) {
|
|
|
|
let resolve_;
|
|
|
|
const tickingPromise = new TickingPromise((resolve) => {
|
|
|
|
resolve_ = resolve;
|
|
|
|
});
|
|
|
|
tickingPromise.ticker = (elapsed) => {
|
|
|
|
this.tick(context, elapsed);
|
|
|
|
}
|
|
|
|
this.once('actionsFinished', () => {
|
|
|
|
resolve_();
|
|
|
|
});
|
|
|
|
return tickingPromise;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-17 23:45:48 -05:00
|
|
|
}
|