Skip to content

Commit fbdf8e8

Browse files
feat: improve dataloader refetch handling (#608)
1 parent cbeee20 commit fbdf8e8

File tree

6 files changed

+96
-127
lines changed

6 files changed

+96
-127
lines changed

packages/use-dataloader/src/DataLoaderProvider.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ type CachedData = Record<string, unknown>
2020
type Reloads = Record<string, () => Promise<void | unknown>>
2121

2222
type UseDataLoaderInitializerArgs<T = unknown> = {
23-
enabled?: boolean
2423
status?: StatusEnum
2524
method: () => PromiseType<T>
2625
pollingInterval?: number

packages/use-dataloader/src/__tests__/DataLoaderProvider.test.tsx

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,11 @@ describe('DataLoaderProvider', () => {
5454
expect(Object.values(result.current.getReloads()).length).toBe(1)
5555
const testRequest = result.current.getRequest(TEST_KEY)
5656
expect(testRequest).toBeDefined()
57-
expect(testRequest?.status).toBe(StatusEnum.IDLE)
57+
expect(testRequest.status).toBe(StatusEnum.IDLE)
5858
act(() => {
5959
// launch should never throw
6060
// eslint-disable-next-line @typescript-eslint/no-floating-promises
61-
testRequest?.launch()
61+
testRequest.load()
6262
})
6363
expect(method).toBeCalledTimes(1)
6464
expect(testRequest.status).toBe(StatusEnum.LOADING)
@@ -92,11 +92,11 @@ describe('DataLoaderProvider', () => {
9292
const testRequest = result.current.getRequest(TEST_KEY)
9393
expect(Object.values(result.current.getReloads()).length).toBe(1)
9494
expect(testRequest).toBeDefined()
95-
expect(testRequest?.status).toBe(StatusEnum.IDLE)
95+
expect(testRequest.status).toBe(StatusEnum.IDLE)
9696
act(() => {
9797
// launch should never throw
9898
// eslint-disable-next-line @typescript-eslint/no-floating-promises
99-
testRequest?.launch()
99+
testRequest.load()
100100
})
101101
expect(method).toBeCalledTimes(1)
102102
await waitFor(() => expect(testRequest.getData()).toBe(true))
@@ -112,14 +112,14 @@ describe('DataLoaderProvider', () => {
112112
wrapper,
113113
})
114114
act(() => {
115-
result.current.getOrAddRequest(TEST_KEY, {
116-
enabled: true,
115+
const request = result.current.getOrAddRequest(TEST_KEY, {
117116
method,
118117
})
119118
result.current.getOrAddRequest(TEST_KEY, {
120-
enabled: true,
121119
method,
122120
})
121+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
122+
request.load()
123123
})
124124
expect(method).toBeCalledTimes(1)
125125
await waitFor(() =>
@@ -198,25 +198,25 @@ describe('DataLoaderProvider', () => {
198198
wrapper: wrapperWith2ConcurrentRequests,
199199
})
200200
act(() => {
201-
result.current.addRequest(TEST_KEY, {
202-
enabled: true,
203-
method,
204-
})
205-
result.current.addRequest(`${TEST_KEY}-2`, {
206-
enabled: true,
207-
method,
208-
})
209-
result.current.addRequest(`${TEST_KEY}-3`, {
210-
enabled: true,
211-
method,
212-
})
213-
result.current.addRequest(`${TEST_KEY}-4`, {
214-
enabled: true,
215-
method,
216-
})
217-
result.current.addRequest(`${TEST_KEY}-5`, {
218-
enabled: true,
219-
method,
201+
;[
202+
result.current.addRequest(TEST_KEY, {
203+
method,
204+
}),
205+
result.current.addRequest(`${TEST_KEY}-2`, {
206+
method,
207+
}),
208+
result.current.addRequest(`${TEST_KEY}-3`, {
209+
method,
210+
}),
211+
result.current.addRequest(`${TEST_KEY}-4`, {
212+
method,
213+
}),
214+
result.current.addRequest(`${TEST_KEY}-5`, {
215+
method,
216+
}),
217+
].forEach(request => {
218+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
219+
request.load()
220220
})
221221
})
222222
expect(method).toBeCalledTimes(2)

packages/use-dataloader/src/__tests__/dataloader.test.ts

Lines changed: 43 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const fakeErrorPromise = () =>
2424
})
2525

2626
describe('Dataloader class', () => {
27-
test('should create instance not enabled then load then destroy', async () => {
27+
test('should create instance then load then destroy', async () => {
2828
const method = jest.fn(fakeSuccessPromise)
2929
const instance = new DataLoader({
3030
key: 'test',
@@ -33,90 +33,71 @@ describe('Dataloader class', () => {
3333
expect(instance.status).toBe(StatusEnum.IDLE)
3434
expect(method).toBeCalledTimes(0)
3535
await instance.load()
36+
expect(instance.status).toBe(StatusEnum.SUCCESS)
3637
expect(method).toBeCalledTimes(1)
3738
await instance.destroy()
3839
instance.clearData()
3940
})
4041

41-
test('should create instance enabled with cancel', async () => {
42+
test('should create instance with cancel', async () => {
4243
const notify = jest.fn()
4344
const method = jest.fn(fakeSuccessPromise)
4445
const instance = new DataLoader({
45-
enabled: true,
4646
key: 'test',
4747
method,
4848
})
4949
instance.addObserver(notify)
50-
expect(instance.status).toBe(StatusEnum.LOADING)
5150
expect(instance.getData()).toBe(undefined)
5251
expect(notify).toBeCalledTimes(0)
52+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
53+
instance.load()
5354
expect(method).toBeCalledTimes(1)
5455
await instance.cancel()
55-
await new Promise(resolve => {
56-
setTimeout(() => {
57-
expect(notify).toBeCalledTimes(1)
58-
resolve(true)
59-
}, PROMISE_TIMEOUT)
60-
})
56+
expect(notify).toBeCalledTimes(1)
6157
expect(instance.getData()).toBe(undefined)
6258
instance.clearData()
6359
})
6460

65-
test('should create instance enabled without cancel', async () => {
61+
test('should create instance without cancel', async () => {
6662
const notify = jest.fn()
6763
const method = jest.fn(fakeSuccessPromise)
6864
const instance = new DataLoader({
69-
enabled: true,
7065
key: 'test',
7166
method,
7267
})
7368
instance.addObserver(notify)
74-
expect(instance.status).toBe(StatusEnum.LOADING)
7569
expect(notify).toBeCalledTimes(0)
70+
expect(instance.status).toBe(StatusEnum.IDLE)
71+
await instance.load()
72+
expect(notify).toBeCalledTimes(2)
7673
expect(method).toBeCalledTimes(1)
77-
await new Promise(resolve => {
78-
setTimeout(() => {
79-
expect(notify).toBeCalledTimes(1)
80-
resolve(true)
81-
}, PROMISE_TIMEOUT)
82-
})
8374
expect(instance.getData()).toBe(true)
8475
instance.getObserversCount()
8576
instance.removeObserver(notify)
8677
instance.removeObserver(notify)
8778
instance.clearData()
8879
})
8980

90-
test('should create instance enabled with null data', async () => {
81+
test('should create instance with null data', async () => {
9182
const method = jest.fn(fakeNullPromise)
9283
const instance = new DataLoader({
93-
enabled: true,
9484
key: 'test',
9585
method,
9686
})
97-
expect(instance.status).toBe(StatusEnum.LOADING)
87+
expect(instance.status).toBe(StatusEnum.IDLE)
88+
await instance.load()
9889
expect(method).toBeCalledTimes(1)
99-
await new Promise(resolve => {
100-
setTimeout(() => {
101-
resolve(true)
102-
}, PROMISE_TIMEOUT)
103-
})
10490
expect(instance.getData()).toBe(undefined)
10591
})
106-
test('should create instance enabled with undefined data', async () => {
92+
test('should create instance with undefined data', async () => {
10793
const method = jest.fn(fakeUndefinedPromise)
10894
const instance = new DataLoader({
109-
enabled: true,
11095
key: 'test',
11196
method,
11297
})
113-
expect(instance.status).toBe(StatusEnum.LOADING)
98+
expect(instance.status).toBe(StatusEnum.IDLE)
99+
await instance.load()
114100
expect(method).toBeCalledTimes(1)
115-
await new Promise(resolve => {
116-
setTimeout(() => {
117-
resolve(true)
118-
}, PROMISE_TIMEOUT)
119-
})
120101
expect(instance.getData()).toBe(undefined)
121102
})
122103

@@ -129,8 +110,8 @@ describe('Dataloader class', () => {
129110
})
130111
instance.addOnCancelListener(onCancel)
131112
instance.addOnCancelListener(onCancel)
132-
// eslint-disable-next-line no-void
133-
void instance.load()
113+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
114+
instance.load()
134115
await instance.cancel()
135116
expect(onCancel).toBeCalledTimes(1)
136117
instance.removeOnCancelListener(onCancel)
@@ -146,8 +127,8 @@ describe('Dataloader class', () => {
146127
})
147128
instance.addOnCancelListener(onCancel)
148129
instance.addOnCancelListener(onCancel)
149-
// eslint-disable-next-line no-void
150-
void instance.load()
130+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
131+
instance.load()
151132
await instance.cancel()
152133
expect(onCancel).toBeCalledTimes(1)
153134
instance.removeOnCancelListener(onCancel)
@@ -190,30 +171,31 @@ describe('Dataloader class', () => {
190171
const instance = new DataLoader({
191172
key: 'test',
192173
method,
193-
pollingInterval: PROMISE_TIMEOUT * 2,
174+
pollingInterval: PROMISE_TIMEOUT,
194175
})
195176
await instance.load()
196177
expect(method).toBeCalledTimes(1)
197-
await new Promise(resolve => {
198-
setTimeout(resolve, PROMISE_TIMEOUT * 3)
178+
await waitForExpect(() => {
179+
expect(method).toBeCalledTimes(2)
199180
})
200-
expect(method).toBeCalledTimes(2)
201-
await new Promise(resolve => {
202-
setTimeout(resolve, PROMISE_TIMEOUT * 3)
181+
await waitForExpect(() => {
182+
expect(method).toBeCalledTimes(3)
203183
})
204-
expect(method).toBeCalledTimes(3)
205184
await instance.load()
206185
await instance.load()
207186
await waitForExpect(() => {
208187
expect(method).toBeCalledTimes(4)
209188
})
189+
await waitForExpect(() => {
190+
expect(method).toBeCalledTimes(5)
191+
})
210192
await instance.load()
211193
await instance.load()
212194
await instance.load(true)
213195
await waitForExpect(() => {
214196
expect(method).toBeCalledTimes(6)
215197
})
216-
instance.setPollingInterval(PROMISE_TIMEOUT * 4)
198+
instance.setPollingInterval(PROMISE_TIMEOUT * 2)
217199
await instance.destroy()
218200
})
219201

@@ -227,24 +209,22 @@ describe('Dataloader class', () => {
227209
})
228210
await instance.load()
229211
expect(method).toBeCalledTimes(1)
230-
await new Promise(resolve => {
231-
setTimeout(resolve, PROMISE_TIMEOUT * 3)
212+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
213+
await instance.load()
214+
await waitForExpect(() => {
215+
expect(method).toBeCalledTimes(2)
232216
})
233-
expect(method).toBeCalledTimes(2)
234-
await new Promise(resolve => {
235-
setTimeout(resolve, PROMISE_TIMEOUT * 3)
217+
await waitForExpect(() => {
218+
expect(method).toBeCalledTimes(3)
236219
})
237-
expect(method).toBeCalledTimes(3)
238-
await instance.load()
239-
await instance.load()
240220
await waitForExpect(() => {
241221
expect(method).toBeCalledTimes(4)
242222
})
243223
await instance.load()
244224
await instance.load()
245225
await instance.load(true)
246226
await waitForExpect(() => {
247-
expect(method).toBeCalledTimes(6)
227+
expect(method).toBeCalledTimes(5)
248228
})
249229
instance.setPollingInterval(PROMISE_TIMEOUT * 4)
250230
await instance.destroy()
@@ -272,24 +252,20 @@ describe('Dataloader class', () => {
272252
const method = jest.fn(fakeSuccessPromise)
273253
const onSuccess = jest.fn()
274254
const instance = new DataLoader({
275-
enabled: true,
276255
key: 'test',
277-
maxDataLifetime: PROMISE_TIMEOUT,
256+
maxDataLifetime: PROMISE_TIMEOUT * 3,
278257
method,
279258
})
280259
instance.addOnSuccessListener(onSuccess)
281-
expect(instance.status).toBe(StatusEnum.LOADING)
260+
expect(instance.status).toBe(StatusEnum.IDLE)
261+
await instance.load()
282262
expect(method).toBeCalledTimes(1)
283-
await new Promise(resolve => {
284-
setTimeout(resolve, PROMISE_TIMEOUT)
285-
})
286263
expect(onSuccess).toBeCalledTimes(1)
287264
await instance.load()
288265
expect(method).toBeCalledTimes(1)
289266
expect(onSuccess).toBeCalledTimes(1)
290-
await new Promise(resolve => {
291-
setTimeout(resolve, PROMISE_TIMEOUT * 2)
292-
})
267+
// Wait until data is outdated
268+
await waitForExpect(() => expect(instance.isDataOutdated).toBeTruthy())
293269
await instance.load()
294270
expect(method).toBeCalledTimes(2)
295271
expect(onSuccess).toBeCalledTimes(2)
@@ -300,11 +276,11 @@ describe('Dataloader class', () => {
300276
DataLoader.maxConcurrent = 2
301277
for (let i = 0; i < 5; i += 1) {
302278
const instance = new DataLoader({
303-
enabled: true,
304279
key: `test-${i}`,
305280
method,
306281
})
307-
expect(instance.status).toBe(StatusEnum.LOADING)
282+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
283+
instance.load()
308284
}
309285
// Because wait for setTimeout tryLaunch in dataloader.ts
310286
await waitForExpect(() => {

0 commit comments

Comments
 (0)