avocado-old/packages/behavior/item/actions.js

75 lines
1.5 KiB
JavaScript
Raw Normal View History

2019-04-08 17:41:20 -05:00
import {compose, TickingPromise} from '@avocado/core';
2019-03-17 23:45:48 -05:00
import {EventEmitter} from '@avocado/mixins';
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
constructor() {
super();
2019-04-07 12:00:11 -05:00
this._index = 0;
2019-03-17 23:45:48 -05:00
this.traversals = [];
this.pending = null;
}
2019-04-20 16:02:52 -05:00
emitFinishedAsync() {
setTimeout(() => {
this.emit('actionsFinished');
}, 0);
}
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
}
tick(context, elapsed) {
if (this.traversals.length === 0) {
2019-04-20 16:02:52 -05:00
this.emitFinishedAsync();
2019-03-17 23:45:48 -05:00
return;
}
if (
this.pending
&& this.pending instanceof TickingPromise
&& 'function' === typeof this.pending.ticker
) {
this.pending.ticker(elapsed);
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) {
result.then(() => this.prologue());
result.catch((error) => {
throw error;
});
this.pending = result;
break;
}
this.prologue();
if (0 === this.index) {
break;
}
}
}
prologue() {
this.pending = null;
2019-04-09 09:39:00 -05:00
if (0 === (this.index = (this.index + 1) % this.traversals.length)) {
2019-04-20 16:02:52 -05:00
this.emitFinishedAsync();
2019-03-17 23:45:48 -05:00
}
}
}