Skip to content

Commit 22a2efd

Browse files
feat(overmind): add waitUntil operator
1 parent 1df8b81 commit 22a2efd

File tree

4 files changed

+104
-6
lines changed

4 files changed

+104
-6
lines changed

packages/node_modules/overmind/src/index.ts

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1511,6 +1511,8 @@ export function throttle<Input, ThisConfig extends IConfiguration = Config>(
15111511
ms: number
15121512
): IOperator<ThisConfig, Input, Input> {
15131513
let timeout
1514+
let previousFinal
1515+
let currentNext
15141516

15151517
return createOperator(
15161518
'throttle',
@@ -1519,13 +1521,38 @@ export function throttle<Input, ThisConfig extends IConfiguration = Config>(
15191521
if (err) next(err, value)
15201522
else {
15211523
if (timeout) {
1522-
final(null, value)
1524+
previousFinal(null, value)
1525+
currentNext = next
15231526
} else {
1524-
next(null, value)
15251527
timeout = setTimeout(() => {
15261528
timeout = null
1529+
currentNext(null, value)
15271530
}, ms)
15281531
}
1532+
previousFinal = final
1533+
currentNext = next
1534+
}
1535+
}
1536+
)
1537+
}
1538+
1539+
export function waitUntil<Input, ThisConfig extends IConfiguration = Config>(
1540+
operation: (state: ThisConfig['state']) => boolean
1541+
): IOperator<ThisConfig, Input, Input> {
1542+
return createOperator<Config>(
1543+
'waitUntil',
1544+
operation.name,
1545+
(err, context, value, next) => {
1546+
if (err) next(err, value)
1547+
else {
1548+
const tree = context.execution.getTrackStateTree()
1549+
const test = () => {
1550+
if (operation(tree.state)) {
1551+
tree.dispose()
1552+
next(null, value)
1553+
}
1554+
}
1555+
tree.trackScope(test, test)
15291556
}
15301557
}
15311558
)

packages/node_modules/overmind/src/operators.test.ts

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
catchError,
1717
tryCatch,
1818
throttle,
19+
waitUntil,
1920
} from './'
2021

2122
describe('OPERATORS', () => {
@@ -219,8 +220,6 @@ describe('OPERATORS', () => {
219220
interface Operator<Input = void, Output = Input>
220221
extends IOperator<Config, Input, Output> {}
221222

222-
interface Action<Input = void> extends IAction<Config, Input> {}
223-
224223
return overmind.actions.test('foo').then(() => {
225224
expect(overmind.state.foo).toBe('FOO')
226225
})
@@ -320,7 +319,7 @@ describe('OPERATORS', () => {
320319
test('throttle', () => {
321320
expect.assertions(1)
322321
const test: Operator = pipe(
323-
throttle(100),
322+
throttle(0),
324323
mutate(({ state }) => state.runCount++)
325324
)
326325
const state = {
@@ -416,7 +415,7 @@ describe('OPERATORS', () => {
416415
expect(overmind.state.foo).toBe('baz')
417416
})
418417
})
419-
test.only('tryCatch - fails', () => {
418+
test('tryCatch - fails', () => {
420419
expect.assertions(1)
421420
const test: Operator<string> = pipe(
422421
tryCatch({
@@ -448,4 +447,39 @@ describe('OPERATORS', () => {
448447
expect(overmind.state.foo).toBe('ehm')
449448
})
450449
})
450+
test('waitUntil', () => {
451+
expect.assertions(1)
452+
const increaseCount: Operator = pipe(
453+
mutate(({ state }) => state.runCount++)
454+
)
455+
const test: Operator = pipe(
456+
waitUntil((state) => state.runCount === 1),
457+
mutate(({ state }) => (state.hasRun = true))
458+
)
459+
const state = {
460+
runCount: 0,
461+
hasRun: false,
462+
}
463+
const config = {
464+
state,
465+
actions: {
466+
increaseCount,
467+
test,
468+
},
469+
}
470+
const overmind = new Overmind(config)
471+
472+
type Config = IConfig<typeof config>
473+
474+
interface Operator<Input = void, Output = Input>
475+
extends IOperator<Config, Input, Output> {}
476+
477+
setTimeout(() => {
478+
overmind.actions.increaseCount()
479+
}, 0)
480+
481+
return overmind.actions.test().then(() => {
482+
expect(overmind.state.runCount).toBe(1)
483+
})
484+
})
451485
})

packages/overmind-website/api/operators.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,13 @@ Hold execution for set time.
121121
h(Example, { name: "api/operators_operator_wait" })
122122
```
123123

124+
## waitUntil
125+
Wait until a state condition is true.
126+
127+
```marksy
128+
h(Example, { name: "api/operators_operator_waituntil" })
129+
```
130+
124131
## when
125132
Go down the true or false path based on the returned value.
126133

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
export default (ts) =>
2+
ts
3+
? [
4+
{
5+
fileName: 'actions.ts',
6+
code: `
7+
import { Operator, pipe, waitUntil } from 'overmind'
8+
import * as o from './operators'
9+
10+
export const search: Operator<string> = pipe(
11+
waitUntil(state => state.count === 3),
12+
o.executeSomething()
13+
)
14+
`,
15+
},
16+
]
17+
: [
18+
{
19+
fileName: 'actions.js',
20+
code: `
21+
import { pipe, waitUntil } from 'overmind'
22+
import * as o from './operators'
23+
24+
export const search = pipe(
25+
waitUntil(state => state.count === 3),
26+
o.executeSomething()
27+
)
28+
`,
29+
},
30+
]

0 commit comments

Comments
 (0)