refactor: promise and tickers
This commit is contained in:
parent
6997e108c0
commit
6eac298671
|
@ -8,7 +8,7 @@ export default class Interactive extends Component {
|
||||||
const script = this.interactScriptInstance.clone();
|
const script = this.interactScriptInstance.clone();
|
||||||
script.context.initiator = initiator;
|
script.context.initiator = initiator;
|
||||||
const {Ticking} = ecs.get(this.entity);
|
const {Ticking} = ecs.get(this.entity);
|
||||||
Ticking.addTickingPromise(script.tickingPromise());
|
Ticking.add(script.ticker());
|
||||||
}
|
}
|
||||||
get interacting() {
|
get interacting() {
|
||||||
return !!this.$$interacting;
|
return !!this.$$interacting;
|
||||||
|
|
|
@ -11,7 +11,7 @@ export default class Plant extends Component {
|
||||||
}
|
}
|
||||||
grow() {
|
grow() {
|
||||||
const {Ticking} = ecs.get(this.entity);
|
const {Ticking} = ecs.get(this.entity);
|
||||||
Ticking.addTickingPromise(this.growScriptInstance.tickingPromise());
|
Ticking.add(this.growScriptInstance.ticker());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,30 +5,30 @@ export default class Ticking extends Component {
|
||||||
return class TickingInstance extends super.instanceFromSchema() {
|
return class TickingInstance extends super.instanceFromSchema() {
|
||||||
|
|
||||||
$$finished = [];
|
$$finished = [];
|
||||||
$$tickingPromises = [];
|
$$tickers = [];
|
||||||
|
|
||||||
addTickingPromise(tickingPromise) {
|
add(ticker) {
|
||||||
this.$$tickingPromises.push(tickingPromise);
|
this.$$tickers.push(ticker);
|
||||||
tickingPromise.then(() => {
|
ticker.then(() => {
|
||||||
this.$$finished.push(tickingPromise);
|
this.$$finished.push(ticker);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
reset() {
|
reset() {
|
||||||
this.$$finished = [];
|
this.$$finished = [];
|
||||||
this.$$tickingPromises = [];
|
this.$$tickers = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
tick(elapsed) {
|
tick(elapsed) {
|
||||||
for (const tickingPromise of this.$$finished) {
|
for (const ticker of this.$$finished) {
|
||||||
this.$$tickingPromises.splice(
|
this.$$tickers.splice(
|
||||||
this.$$tickingPromises.indexOf(tickingPromise),
|
this.$$tickers.indexOf(ticker),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.$$finished = [];
|
this.$$finished = [];
|
||||||
for (const tickingPromise of this.$$tickingPromises) {
|
for (const ticker of this.$$tickers) {
|
||||||
tickingPromise.tick(elapsed);
|
ticker.tick(elapsed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ export default class Wielder extends Component {
|
||||||
script.context.ecs = ecs;
|
script.context.ecs = ecs;
|
||||||
script.context.item = activeItem;
|
script.context.item = activeItem;
|
||||||
script.context.wielder = entity;
|
script.context.wielder = entity;
|
||||||
Ticking.addTickingPromise(script.tickingPromise());
|
Ticking.add(script.ticker());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,14 +69,14 @@ export default class Colliders extends System {
|
||||||
const script = entity.Collider.collisionStartScriptInstance.clone();
|
const script = entity.Collider.collisionStartScriptInstance.clone();
|
||||||
script.context.intersections = intersections;
|
script.context.intersections = intersections;
|
||||||
script.context.other = other;
|
script.context.other = other;
|
||||||
entity.Ticking.addTickingPromise(script.tickingPromise());
|
entity.Ticking.add(script.ticker());
|
||||||
}
|
}
|
||||||
if (other.Collider.collisionStartScriptInstance) {
|
if (other.Collider.collisionStartScriptInstance) {
|
||||||
const script = other.Collider.collisionStartScriptInstance.clone();
|
const script = other.Collider.collisionStartScriptInstance.clone();
|
||||||
script.context.intersections = intersections
|
script.context.intersections = intersections
|
||||||
.map(([l, r]) => [r, l]);
|
.map(([l, r]) => [r, l]);
|
||||||
script.context.other = entity;
|
script.context.other = entity;
|
||||||
other.Ticking.addTickingPromise(script.tickingPromise());
|
other.Ticking.add(script.ticker());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const i in intersections) {
|
for (const i in intersections) {
|
||||||
|
@ -127,12 +127,12 @@ export default class Colliders extends System {
|
||||||
if (entity.Collider.collisionEndScriptInstance) {
|
if (entity.Collider.collisionEndScriptInstance) {
|
||||||
const script = entity.Collider.collisionEndScriptInstance.clone();
|
const script = entity.Collider.collisionEndScriptInstance.clone();
|
||||||
script.context.other = other;
|
script.context.other = other;
|
||||||
entity.Ticking.addTickingPromise(script.tickingPromise());
|
entity.Ticking.add(script.ticker());
|
||||||
}
|
}
|
||||||
if (other.Collider.collisionEndScriptInstance) {
|
if (other.Collider.collisionEndScriptInstance) {
|
||||||
const script = other.Collider.collisionEndScriptInstance.clone();
|
const script = other.Collider.collisionEndScriptInstance.clone();
|
||||||
script.context.other = entity;
|
script.context.other = entity;
|
||||||
other.Ticking.addTickingPromise(script.tickingPromise());
|
other.Ticking.add(script.ticker());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import TickingPromise from '@/util/ticking-promise.js';
|
import {Ticker} from '@/util/promise.js';
|
||||||
|
|
||||||
export default function delta(object, properties) {
|
export default function delta(object, properties) {
|
||||||
const deltas = {};
|
const deltas = {};
|
||||||
|
@ -12,7 +12,7 @@ export default function delta(object, properties) {
|
||||||
deltas[key] = delta;
|
deltas[key] = delta;
|
||||||
}
|
}
|
||||||
let stop;
|
let stop;
|
||||||
const promise = new TickingPromise(
|
const promise = new Ticker(
|
||||||
(resolve) => {
|
(resolve) => {
|
||||||
stop = resolve;
|
stop = resolve;
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import {withResolvers} from '@/util/promise.js';
|
import {Ticker, withResolvers} from '@/util/promise.js';
|
||||||
import TickingPromise from '@/util/ticking-promise.js';
|
|
||||||
|
|
||||||
const Modulators = {
|
const Modulators = {
|
||||||
flat: () => 0.5,
|
flat: () => 0.5,
|
||||||
|
@ -44,7 +43,7 @@ export default function lfo(object, properties) {
|
||||||
oscillators[key] = oscillator;
|
oscillators[key] = oscillator;
|
||||||
}
|
}
|
||||||
let stop;
|
let stop;
|
||||||
const promise = new TickingPromise(
|
const promise = new Ticker(
|
||||||
(resolve) => {
|
(resolve) => {
|
||||||
stop = resolve;
|
stop = resolve;
|
||||||
Promise.all(promises).then(resolve);
|
Promise.all(promises).then(resolve);
|
||||||
|
|
|
@ -1,3 +1,10 @@
|
||||||
|
export const all = Promise.all.bind(Promise);
|
||||||
|
export const allSettled = Promise.allSettled.bind(Promise);
|
||||||
|
export const any = Promise.any.bind(Promise);
|
||||||
|
export const race = Promise.race.bind(Promise);
|
||||||
|
export const reject = Promise.reject.bind(Promise);
|
||||||
|
export const resolve = Promise.resolve.bind(Promise);
|
||||||
|
|
||||||
export function withResolvers() {
|
export function withResolvers() {
|
||||||
let resolve, reject, promise = new Promise((res, rej) => {
|
let resolve, reject, promise = new Promise((res, rej) => {
|
||||||
resolve = res;
|
resolve = res;
|
||||||
|
@ -5,3 +12,57 @@ export function withResolvers() {
|
||||||
});
|
});
|
||||||
return {promise, reject, resolve};
|
return {promise, reject, resolve};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class Ticker extends Promise {
|
||||||
|
|
||||||
|
constructor(executor, ticker) {
|
||||||
|
let _reject;
|
||||||
|
let _resolve;
|
||||||
|
super((resolve, reject) => {
|
||||||
|
_reject = reject;
|
||||||
|
_resolve = resolve;
|
||||||
|
if (executor) {
|
||||||
|
executor(resolve, reject);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.reject = _reject;
|
||||||
|
this.resolve = _resolve;
|
||||||
|
this.ticker = ticker;
|
||||||
|
}
|
||||||
|
|
||||||
|
static all(promises) {
|
||||||
|
const tickers = [];
|
||||||
|
for (let i = 0; i < promises.length; i++) {
|
||||||
|
const promise = promises[i];
|
||||||
|
if (promise instanceof Ticker) {
|
||||||
|
tickers.push(promise);
|
||||||
|
// After resolution, stop ticking the promise.
|
||||||
|
promise.then(() => {
|
||||||
|
tickers.splice(tickers.indexOf(promise), 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* v8 ignore next 3 */
|
||||||
|
if (0 === tickers.length) {
|
||||||
|
return super.all(promises);
|
||||||
|
}
|
||||||
|
return new Ticker(
|
||||||
|
(resolve, reject) => {
|
||||||
|
super.all(promises)
|
||||||
|
.then(resolve)
|
||||||
|
/* v8 ignore next */
|
||||||
|
.catch(reject);
|
||||||
|
},
|
||||||
|
(elapsed) => {
|
||||||
|
for (let i = 0; i < tickers.length; i++) {
|
||||||
|
tickers[i].tick(elapsed);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
tick(elapsed) {
|
||||||
|
this.ticker(elapsed, this.resolve, this.reject);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,17 +1,17 @@
|
||||||
import {expect, test} from 'vitest';
|
import {expect, test} from 'vitest';
|
||||||
|
|
||||||
import TickingPromise from './ticking-promise.js';
|
import {Ticker} from './promise.js';
|
||||||
|
|
||||||
test('runs executor', async () => {
|
test('runs executor', async () => {
|
||||||
expect(
|
expect(
|
||||||
await new TickingPromise((resolve) => {
|
await new Ticker((resolve) => {
|
||||||
resolve(32);
|
resolve(32);
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.to.equal(32);
|
.to.equal(32);
|
||||||
expect(
|
expect(
|
||||||
async () => {
|
async () => {
|
||||||
await new TickingPromise((resolve, reject) => {
|
await new Ticker((resolve, reject) => {
|
||||||
reject(new Error(''));
|
reject(new Error(''));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ test('runs executor', async () => {
|
||||||
test('ticks and resolves', async () => {
|
test('ticks and resolves', async () => {
|
||||||
let done = false;
|
let done = false;
|
||||||
let e = 0;
|
let e = 0;
|
||||||
const tp = new TickingPromise(undefined, (elapsed, resolve) => {
|
const tp = new Ticker(undefined, (elapsed, resolve) => {
|
||||||
e += elapsed;
|
e += elapsed;
|
||||||
if (1 === e) {
|
if (1 === e) {
|
||||||
done = true;
|
done = true;
|
||||||
|
@ -49,7 +49,7 @@ test('ticks and resolves', async () => {
|
||||||
|
|
||||||
test('ticks and rejects', async () => {
|
test('ticks and rejects', async () => {
|
||||||
let caught = false;
|
let caught = false;
|
||||||
const tp = new TickingPromise(undefined, (elapsed, resolve, reject) => {
|
const tp = new Ticker(undefined, (elapsed, resolve, reject) => {
|
||||||
reject(new Error());
|
reject(new Error());
|
||||||
});
|
});
|
||||||
tp.catch(() => {
|
tp.catch(() => {
|
||||||
|
@ -66,21 +66,21 @@ test('ticks and rejects', async () => {
|
||||||
test('handles all', async () => {
|
test('handles all', async () => {
|
||||||
let done = 0;
|
let done = 0;
|
||||||
let e1 = 0, e2 = 0;
|
let e1 = 0, e2 = 0;
|
||||||
const tp1 = new TickingPromise(undefined, (elapsed, resolve) => {
|
const tp1 = new Ticker(undefined, (elapsed, resolve) => {
|
||||||
e1 += elapsed;
|
e1 += elapsed;
|
||||||
if (1 === e1) {
|
if (1 === e1) {
|
||||||
done += 1;
|
done += 1;
|
||||||
resolve(16);
|
resolve(16);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const tp2 = new TickingPromise(undefined, (elapsed, resolve) => {
|
const tp2 = new Ticker(undefined, (elapsed, resolve) => {
|
||||||
e2 += elapsed;
|
e2 += elapsed;
|
||||||
if (2 === e2) {
|
if (2 === e2) {
|
||||||
done += 1;
|
done += 1;
|
||||||
resolve(32);
|
resolve(32);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const tpa = TickingPromise.all([
|
const tpa = Ticker.all([
|
||||||
Promise.resolve(8),
|
Promise.resolve(8),
|
||||||
tp1,
|
tp1,
|
||||||
tp2,
|
tp2,
|
|
@ -2,10 +2,10 @@ import {parse as acornParse} from 'acorn';
|
||||||
import {LRUCache} from 'lru-cache';
|
import {LRUCache} from 'lru-cache';
|
||||||
|
|
||||||
import Sandbox from '@/astride/sandbox.js';
|
import Sandbox from '@/astride/sandbox.js';
|
||||||
import TickingPromise from '@/util/ticking-promise.js';
|
|
||||||
import delta from '@/util/delta.js';
|
import delta from '@/util/delta.js';
|
||||||
import lfo from '@/util/lfo.js';
|
import lfo from '@/util/lfo.js';
|
||||||
import * as MathUtil from '@/util/math.js';
|
import * as MathUtil from '@/util/math.js';
|
||||||
|
import * as PromiseUtil from '@/util/promise.js';
|
||||||
import transition from '@/util/transition.js';
|
import transition from '@/util/transition.js';
|
||||||
|
|
||||||
function parse(code, options = {}) {
|
function parse(code, options = {}) {
|
||||||
|
@ -43,7 +43,7 @@ export default class Script {
|
||||||
delta,
|
delta,
|
||||||
lfo,
|
lfo,
|
||||||
Math: MathUtil,
|
Math: MathUtil,
|
||||||
Promise,
|
Promise: PromiseUtil,
|
||||||
transition,
|
transition,
|
||||||
wait: (seconds) => (
|
wait: (seconds) => (
|
||||||
new Promise((resolve) => {
|
new Promise((resolve) => {
|
||||||
|
@ -95,7 +95,7 @@ export default class Script {
|
||||||
|
|
||||||
tick(elapsed, resolve, reject) {
|
tick(elapsed, resolve, reject) {
|
||||||
if (this.promise) {
|
if (this.promise) {
|
||||||
if (this.promise instanceof TickingPromise) {
|
if (this.promise instanceof PromiseUtil.Ticker) {
|
||||||
this.promise.tick(elapsed);
|
this.promise.tick(elapsed);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -128,8 +128,8 @@ export default class Script {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tickingPromise() {
|
ticker() {
|
||||||
return new TickingPromise(
|
return new PromiseUtil.Ticker(
|
||||||
() => {},
|
() => {},
|
||||||
(elapsed, resolve, reject) => {
|
(elapsed, resolve, reject) => {
|
||||||
this.tick(elapsed, resolve, reject);
|
this.tick(elapsed, resolve, reject);
|
||||||
|
@ -137,18 +137,18 @@ export default class Script {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static tickingPromise(code, context = {}) {
|
static ticker(code, context = {}) {
|
||||||
let tickingPromise;
|
let ticker;
|
||||||
return new TickingPromise(
|
return new PromiseUtil.Ticker(
|
||||||
(resolve) => {
|
(resolve) => {
|
||||||
this.fromCode(code, context)
|
this.fromCode(code, context)
|
||||||
.then((script) => {
|
.then((script) => {
|
||||||
tickingPromise = script.tickingPromise();
|
ticker = script.ticker();
|
||||||
resolve(tickingPromise);
|
resolve(ticker);
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
(elapsed) => {
|
(elapsed) => {
|
||||||
tickingPromise?.tick?.(elapsed);
|
ticker?.tick?.(elapsed);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
export default class TickingPromise extends Promise {
|
|
||||||
|
|
||||||
constructor(executor, ticker) {
|
|
||||||
let _reject;
|
|
||||||
let _resolve;
|
|
||||||
super((resolve, reject) => {
|
|
||||||
_reject = reject;
|
|
||||||
_resolve = resolve;
|
|
||||||
if (executor) {
|
|
||||||
executor(resolve, reject);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.reject = _reject;
|
|
||||||
this.resolve = _resolve;
|
|
||||||
this.ticker = ticker;
|
|
||||||
}
|
|
||||||
|
|
||||||
static all(promises) {
|
|
||||||
const tickingPromises = [];
|
|
||||||
for (let i = 0; i < promises.length; i++) {
|
|
||||||
const promise = promises[i];
|
|
||||||
if (promise instanceof TickingPromise) {
|
|
||||||
tickingPromises.push(promise);
|
|
||||||
// After resolution, stop ticking the promise.
|
|
||||||
promise.then(() => {
|
|
||||||
tickingPromises.splice(tickingPromises.indexOf(promise), 1);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* v8 ignore next 3 */
|
|
||||||
if (0 === tickingPromises.length) {
|
|
||||||
return super.all(promises);
|
|
||||||
}
|
|
||||||
return new TickingPromise(
|
|
||||||
(resolve, reject) => {
|
|
||||||
super.all(promises)
|
|
||||||
.then(resolve)
|
|
||||||
/* v8 ignore next */
|
|
||||||
.catch(reject);
|
|
||||||
},
|
|
||||||
(elapsed) => {
|
|
||||||
for (let i = 0; i < tickingPromises.length; i++) {
|
|
||||||
tickingPromises[i].tick(elapsed);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
tick(elapsed) {
|
|
||||||
this.ticker(elapsed, this.resolve, this.reject);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
import TickingPromise from '@/util/ticking-promise.js';
|
import {Ticker} from '@/util/promise.js';
|
||||||
|
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
const Easing = {
|
const Easing = {
|
||||||
|
@ -152,7 +152,7 @@ export default function transition(object, properties) {
|
||||||
transitions[key] = transition;
|
transitions[key] = transition;
|
||||||
}
|
}
|
||||||
let stop;
|
let stop;
|
||||||
const promise = new TickingPromise(
|
const promise = new Ticker(
|
||||||
(resolve) => {
|
(resolve) => {
|
||||||
stop = resolve;
|
stop = resolve;
|
||||||
},
|
},
|
||||||
|
|
|
@ -48,7 +48,10 @@ for (let i = 0; i < 10; ++i) {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
const l = lfo(
|
tomato.Ticking.add(
|
||||||
|
Promise.Ticker.all([
|
||||||
|
d.promise,
|
||||||
|
lfo(
|
||||||
d.deltas.y,
|
d.deltas.y,
|
||||||
{
|
{
|
||||||
delta: {
|
delta: {
|
||||||
|
@ -59,8 +62,8 @@ for (let i = 0; i < 10; ++i) {
|
||||||
offset: -0.5,
|
offset: -0.5,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
).promise,
|
||||||
const ls = lfo(
|
lfo(
|
||||||
tomato.Sprite,
|
tomato.Sprite,
|
||||||
{
|
{
|
||||||
scaleX: {
|
scaleX: {
|
||||||
|
@ -80,19 +83,7 @@ for (let i = 0; i < 10; ++i) {
|
||||||
offset: -0.5,
|
offset: -0.5,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
).promise,
|
||||||
|
|
||||||
tomato.Ticking.addTickingPromise(
|
|
||||||
d.promise,
|
|
||||||
);
|
|
||||||
tomato.Ticking.addTickingPromise(
|
|
||||||
l.promise,
|
|
||||||
);
|
|
||||||
tomato.Ticking.addTickingPromise(
|
|
||||||
ls.promise,
|
|
||||||
);
|
|
||||||
|
|
||||||
tomato.Ticking.addTickingPromise(
|
|
||||||
delta(
|
delta(
|
||||||
tomato.Position,
|
tomato.Position,
|
||||||
{
|
{
|
||||||
|
@ -102,8 +93,6 @@ for (let i = 0; i < 10; ++i) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
).promise,
|
).promise,
|
||||||
);
|
|
||||||
tomato.Ticking.addTickingPromise(
|
|
||||||
delta(
|
delta(
|
||||||
tomato.Position,
|
tomato.Position,
|
||||||
{
|
{
|
||||||
|
@ -113,6 +102,7 @@ for (let i = 0; i < 10; ++i) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
).promise,
|
).promise,
|
||||||
|
]),
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user