2019-04-28 23:45:03 -05:00
|
|
|
import {compose, EventEmitter, TickingPromise} from '@avocado/core';
|
2019-03-17 23:45:48 -05:00
|
|
|
|
2019-04-08 17:41:20 -05:00
|
|
|
const decorate = compose(
|
|
|
|
EventEmitter,
|
|
|
|
);
|
|
|
|
|
2020-06-23 11:19:59 -05:00
|
|
|
class Actions {
|
2019-03-17 23:45:48 -05:00
|
|
|
|
2020-06-23 11:19:59 -05:00
|
|
|
constructor(expressions) {
|
|
|
|
this.expressions = 'function' === typeof expressions ? expressions() : expressions;
|
2019-04-07 12:00:11 -05:00
|
|
|
this._index = 0;
|
2020-06-23 11:19:59 -05:00
|
|
|
this.promise = null;
|
2019-03-17 23:45:48 -05:00
|
|
|
}
|
|
|
|
|
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) {
|
2019-09-08 19:50:39 -05:00
|
|
|
// Empty resolves immediately.
|
2020-06-23 11:19:59 -05:00
|
|
|
if (this.expressions.length === 0) {
|
2019-04-23 00:30:44 -05:00
|
|
|
this.emitFinished();
|
2019-03-17 23:45:48 -05:00
|
|
|
return;
|
|
|
|
}
|
2019-09-08 19:50:39 -05:00
|
|
|
// If the action promise ticks, tick it.
|
2020-06-23 11:19:59 -05:00
|
|
|
if (this.promise && this.promise instanceof TickingPromise) {
|
|
|
|
this.promise.tick(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) {
|
2019-09-08 19:50:39 -05:00
|
|
|
// Run the action.
|
2020-06-23 11:19:59 -05:00
|
|
|
const result = this.expressions[this.index](context);
|
2019-09-08 19:50:39 -05:00
|
|
|
// Deferred result.
|
2019-03-17 23:45:48 -05:00
|
|
|
if (result instanceof Promise) {
|
2020-06-23 11:19:59 -05:00
|
|
|
this.promise = result;
|
|
|
|
this.promise.catch(console.error).finally(() => this.prologue());
|
2019-03-17 23:45:48 -05:00
|
|
|
break;
|
|
|
|
}
|
2019-09-08 19:50:39 -05:00
|
|
|
// Immediate result.
|
2019-03-17 23:45:48 -05:00
|
|
|
this.prologue();
|
2019-09-08 19:50:39 -05:00
|
|
|
// Need to break out immediately if required.
|
2019-03-17 23:45:48 -05:00
|
|
|
if (0 === this.index) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-06 00:09:51 -05:00
|
|
|
parallel(context) {
|
2020-06-23 11:19:59 -05:00
|
|
|
const results = this.expressions.map((expression) => expression(context));
|
|
|
|
for (let i = 0; i < results.length; i++) {
|
|
|
|
const result = results[i];
|
|
|
|
if (result instanceof TickingPromise) {
|
|
|
|
return TickingPromise.all(results);
|
|
|
|
}
|
|
|
|
if (result instanceof Promise) {
|
|
|
|
return Promise.all(results);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return results;
|
2019-06-06 00:09:51 -05:00
|
|
|
}
|
|
|
|
|
2019-03-17 23:45:48 -05:00
|
|
|
prologue() {
|
2019-09-08 19:50:39 -05:00
|
|
|
// Clear out the action promise.
|
2020-06-23 11:19:59 -05:00
|
|
|
this.promise = null;
|
2019-09-08 19:50:39 -05:00
|
|
|
// Increment and wrap the index.
|
2020-06-23 11:19:59 -05:00
|
|
|
this.index = (this.index + 1) % this.expressions.length;
|
2019-09-08 19:50:39 -05:00
|
|
|
// If rolled over, the actions are finished.
|
|
|
|
if (0 === this.index) {
|
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) {
|
2019-09-08 19:31:14 -05:00
|
|
|
return this.tickingPromise(context);
|
2019-06-07 00:14:16 -05:00
|
|
|
}
|
|
|
|
|
2019-09-08 07:39:55 -05:00
|
|
|
tickingPromise(context) {
|
|
|
|
return new TickingPromise(
|
|
|
|
(resolve) => {
|
2019-09-08 19:50:39 -05:00
|
|
|
this.once('actionsFinished', resolve);
|
2019-09-08 07:39:55 -05:00
|
|
|
},
|
|
|
|
(elapsed) => {
|
|
|
|
this.tick(context, elapsed);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-03-17 23:45:48 -05:00
|
|
|
}
|
2020-06-23 11:19:59 -05:00
|
|
|
|
|
|
|
export default decorate(Actions);
|