feat: ticking promise
This commit is contained in:
parent
1a908bc0af
commit
9e5efdf413
53
app/util/ticking-promise.js
Normal file
53
app/util/ticking-promise.js
Normal file
|
@ -0,0 +1,53 @@
|
|||
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);
|
||||
}
|
||||
|
||||
}
|
100
app/util/ticking-promise.test.js
Normal file
100
app/util/ticking-promise.test.js
Normal file
|
@ -0,0 +1,100 @@
|
|||
import {expect, test} from 'vitest';
|
||||
|
||||
import TickingPromise from './ticking-promise.js';
|
||||
|
||||
test('runs executor', async () => {
|
||||
expect(
|
||||
await new TickingPromise((resolve, reject) => {
|
||||
resolve(32);
|
||||
}),
|
||||
)
|
||||
.to.equal(32);
|
||||
expect(
|
||||
async () => {
|
||||
await new TickingPromise((resolve, reject) => {
|
||||
reject(new Error(''));
|
||||
})
|
||||
}
|
||||
)
|
||||
.rejects.toThrowError('');
|
||||
});
|
||||
|
||||
test('ticks and resolves', async () => {
|
||||
let done = false;
|
||||
let e = 0;
|
||||
const tp = new TickingPromise(undefined, (elapsed, resolve) => {
|
||||
e += elapsed;
|
||||
if (1 === e) {
|
||||
done = true;
|
||||
resolve(16);
|
||||
}
|
||||
});
|
||||
expect(done)
|
||||
.to.be.false;
|
||||
tp.tick(0.25);
|
||||
expect(done)
|
||||
.to.be.false;
|
||||
tp.tick(0.25);
|
||||
expect(done)
|
||||
.to.be.false;
|
||||
tp.tick(0.25);
|
||||
expect(done)
|
||||
.to.be.false;
|
||||
tp.tick(0.25);
|
||||
expect(done)
|
||||
.to.be.true;
|
||||
expect(await tp)
|
||||
.to.equal(16);
|
||||
});
|
||||
|
||||
test('ticks and rejects', async () => {
|
||||
let caught = false;
|
||||
const tp = new TickingPromise(undefined, (elapsed, resolve, reject) => {
|
||||
reject(new Error());
|
||||
});
|
||||
tp.catch(() => {
|
||||
caught = true;
|
||||
});
|
||||
expect(caught)
|
||||
.to.be.false;
|
||||
tp.tick(0.25);
|
||||
await Promise.resolve();
|
||||
expect(caught)
|
||||
.to.be.true;
|
||||
});
|
||||
|
||||
test('handles all', async () => {
|
||||
let done = 0;
|
||||
let e1 = 0, e2 = 0;
|
||||
const tp1 = new TickingPromise(undefined, (elapsed, resolve) => {
|
||||
e1 += elapsed;
|
||||
if (1 === e1) {
|
||||
done += 1;
|
||||
resolve(16);
|
||||
}
|
||||
});
|
||||
const tp2 = new TickingPromise(undefined, (elapsed, resolve) => {
|
||||
e2 += elapsed;
|
||||
if (2 === e2) {
|
||||
done += 1;
|
||||
resolve(32);
|
||||
}
|
||||
});
|
||||
const tpa = TickingPromise.all([
|
||||
Promise.resolve(8),
|
||||
tp1,
|
||||
tp2,
|
||||
]);
|
||||
expect(done)
|
||||
.to.equal(0);
|
||||
while (2 !== done) {
|
||||
tpa.tick(0.25);
|
||||
await Promise.resolve();
|
||||
}
|
||||
expect(e1)
|
||||
.to.equal(1);
|
||||
expect(e2)
|
||||
.to.equal(2);
|
||||
expect(await tpa)
|
||||
.to.deep.equal([8, 16, 32]);
|
||||
});
|
Loading…
Reference in New Issue
Block a user