@astral/mobx-query 1.18.2 → 1.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,6 +10,7 @@
10
10
  - ⚡️️️️ Фоновая подгрузка данных для работы с WebSocket
11
11
  - ⚡️️️️ Возможность тестирования
12
12
 
13
+
13
14
  ## Table of contents
14
15
 
15
16
  - [Installation](#installation)
@@ -25,7 +26,13 @@
25
26
  - [Создание InfiniteQuerySet](#создание-infinitequerygroups)
26
27
  - [Использование InfiniteQuerySet](#использование-infinitequerygroups)
27
28
  - [Загрузка данных](#загрузка-данных)
29
+ - [Статус дозагрузки fetchMore](#статус-дозагрузки-fetchmore)
30
+ - [Старт не с начала списка](#старт-не-с-начала-списка)
31
+ - [Запоминание последней успешной позиции](#запоминание-последней-успешной-позиции)
32
+ - [Обратная дозагрузка данных](#обратная-дозагрузка-данных)
33
+ - [Курсорная пагинация](#курсорная-пагинация)
28
34
  - [isEndReached. Определение конца списка](#isendreached-определение-конца-списка)
35
+ - [isStartReached. Определение начала списка](#isstartreached-определение-начала-списка)
29
36
  - [Изменение количества запрашиваемых записей](#изменение-количества-запрашиваемых-записей)
30
37
  - [MutationSet](#mutationset)
31
38
  - [Создание mutations](#создание-и-использование-mutations)
@@ -340,6 +347,189 @@ await when(() => !query.isLoading);
340
347
  docListQuery.data.length; // 60 записей
341
348
  ```
342
349
 
350
+ #### Статус дозагрузки `fetchMore`
351
+
352
+ `fetchMoreStatus` содержит отдельные статусы дозагрузки следующей страницы. Это позволяет отдельно отслеживать состояние `fetchMore`, не смешивая его с общим статусом `InfiniteQuery`.
353
+
354
+ ```ts
355
+ import { when } from 'mobx';
356
+
357
+ const createDocListInfiniteQuery = (filters: Omit<DocsDTO.DocListFilters, 'offset' | 'count'>) =>
358
+ cacheService.createInfiniteQuery(['docList', filters],
359
+ (params: { offset: number; count: number }) => docsEndpoints.getDocList({ offset: params.offset, count: params.count, ...filters })
360
+ );
361
+
362
+ const docListQuery = createDocListInfiniteQuery({ search: 'test' });
363
+
364
+ await docListQuery.async();
365
+
366
+ docListQuery.fetchMore();
367
+
368
+ docListQuery.fetchMoreStatus.isLoading; // true
369
+ docListQuery.fetchMoreStatus.isSuccess; // false
370
+ docListQuery.fetchMoreStatus.isError; // false
371
+
372
+ await when(() => !docListQuery.fetchMoreStatus.isLoading);
373
+
374
+ docListQuery.fetchMoreStatus.isLoading; // false
375
+ docListQuery.fetchMoreStatus.isSuccess; // true
376
+ docListQuery.fetchMoreStatus.error; // undefined
377
+ ```
378
+
379
+ Если `fetchMore` завершится ошибкой, `fetchMoreStatus.isError` станет `true`, а `fetchMoreStatus.error` будет содержать ошибку. Значение `offset` будет возвращено к предыдущему успешному состоянию, поэтому повторный вызов `fetchMore` повторит запрос той же страницы.
380
+
381
+ ### Старт не с начала списка
382
+
383
+ Для сценариев восстановления позиции списка можно передать `initialOffset` или `initialCursor`.
384
+ Эти значения используются только для самого первого запроса нового инстанса `InfiniteQuery`.
385
+ После `invalidate()` следующий запрос снова начнется с начала списка.
386
+
387
+ Это полезно, когда нужно восстановить список с определенной позиции, например после возврата на страницу в SPA или при открытии ссылки, в которой уже закодирована нужная точка входа в список.
388
+
389
+ #### Offset-пагинация
390
+
391
+ Если API использует смещение, передайте `initialOffset`.
392
+
393
+ ```ts
394
+ const docListQuery = docsFetcher.infiniteQueries.docList.createWithConfig(
395
+ {
396
+ initialOffset: 120,
397
+ },
398
+ { search: 'test' },
399
+ );
400
+
401
+ await docListQuery.async(); // первый запрос будет выполнен с offset=120
402
+
403
+ docListQuery.invalidate();
404
+ await docListQuery.async(); // после invalidate запрос снова начнется с offset=0
405
+ ```
406
+
407
+ #### Курсорная пагинация
408
+
409
+ Если API использует курсор, передайте `initialCursor`.
410
+
411
+ ```ts
412
+ const docListQuery = docsFetcher.infiniteQueries.docList.createWithConfig(
413
+ {
414
+ initialCursor: { id: 'doc-120' },
415
+ },
416
+ { search: 'test' },
417
+ );
418
+
419
+ await docListQuery.async(); // первый запрос будет выполнен с cursor={ id: 'doc-120' }
420
+
421
+ docListQuery.invalidate();
422
+ await docListQuery.async(); // после invalidate запрос снова начнется без курсора
423
+ ```
424
+
425
+ ### Запоминание последней успешной позиции
426
+
427
+ ```ts
428
+ await docListQuery.async(); // запрос на получение первых 30 записей
429
+
430
+ docListQuery.fetchMore({
431
+ onSuccess: ({ offset, cursor }) => {
432
+ savedOffset = offset; // запоминаем offset последней успешной дозагрузки
433
+ savedCursor = cursor; // запоминаем cursor последней успешной дозагрузки
434
+ },
435
+ });
436
+
437
+ docsFetcher.infiniteQueries.docList.createWithConfig(
438
+ { search: 'test' },
439
+ {
440
+ initialOffset: savedOffset,
441
+ initialCursor: savedCursor,
442
+ },
443
+ ); // новый инстанс продолжит загрузку с сохраненной позиции
444
+ ```
445
+
446
+ ```ts
447
+ const searchParams = new URLSearchParams(window.location.search);
448
+
449
+ await docListQuery.async();
450
+
451
+ docListQuery.fetchMore({
452
+ onSuccess: ({ offset, cursor }) => {
453
+ searchParams.set('offset', String(offset));
454
+ searchParams.set('cursorId', cursor.id);
455
+
456
+ window.history.replaceState(
457
+ null,
458
+ '',
459
+ `?${searchParams.toString()}`,
460
+ );
461
+ },
462
+ });
463
+
464
+ const restoredQuery = docsFetcher.infiniteQueries.docList.createWithConfig(
465
+ {
466
+ initialOffset: Number(searchParams.get('offset') ?? 0),
467
+ initialCursor: searchParams.get('cursorId')
468
+ ? { id: searchParams.get('cursorId')! }
469
+ : undefined,
470
+ },
471
+ { search: 'test' },
472
+ );
473
+ ```
474
+
475
+ ### Обратная дозагрузка данных
476
+
477
+ По умолчанию `fetchMore()` загружает следующую страницу и добавляет ее в конец списка.
478
+ Вызов `fetchMore({ direction: 'backward' })` загружает предыдущую страницу и добавляет ее в начало списка.
479
+
480
+ ```ts
481
+ const docListQuery = docsFetcher.infiniteQueries.docList.createWithConfig(
482
+ { initialOffset: 60 },
483
+ { search: 'test' },
484
+ );
485
+
486
+ await docListQuery.async(); // будут загружены записи начиная с offset=60
487
+
488
+ docListQuery.fetchMore({ direction: 'backward' }); // будет запрошена предыдущая страница
489
+ ```
490
+
491
+ При `fetchMore({ direction: 'backward' })` библиотека уменьшает `offset`, передает в `execute` первый элемент текущего списка как `cursor` и указывает `direction: 'backward'`.
492
+
493
+ ### Курсорная пагинация
494
+
495
+ ```ts
496
+ type Doc = {
497
+ id: string;
498
+ title: string;
499
+ };
500
+
501
+ const docsFetcher = {
502
+ infiniteQueries: {
503
+ docList: mobxQuery.createInfiniteQuerySet(
504
+ (filters: Omit<DocsDTO.DocListFilters, 'count'>) => ({
505
+ execute: ({ count, cursor, direction }) =>
506
+ docsEndpoint
507
+ .getDocList({
508
+ count,
509
+ cursorId: cursor?.id,
510
+ direction,
511
+ ...filters,
512
+ })
513
+ .then(({ data }) => data.list as Doc[]),
514
+ }),
515
+ ),
516
+ },
517
+ };
518
+
519
+ const docListQuery = docsFetcher.infiniteQueries.docList.createWithConfig(
520
+ { initialCursor: { id: 'doc-120' } },
521
+ { search: 'test' },
522
+ );
523
+
524
+ await docListQuery.async(); // при первом запросе execute получит initialCursor, если он задан
525
+
526
+ docListQuery.fetchMore(); // execute получит последний элемент списка и direction: 'forward'
527
+
528
+ docListQuery.fetchMore({ direction: 'backward' }); // execute получит первый элемент списка и direction: 'backward'
529
+ ```
530
+
531
+ Во всех остальных запросах `cursor` будет `undefined`, включая первый запрос без `initialCursor` и повторный запрос после `invalidate()`.
532
+
343
533
  ### `isEndReached`. Определение конца списка
344
534
 
345
535
  Флаг `isEndReached` будет установлен в `true`, если записи для загрузки закончились:
@@ -364,6 +554,11 @@ docListQuery.isEndReached; // true
364
554
 
365
555
  Флаг `isEndReached` устанавливается в `true`, когда количество полученных элементов меньше запрошенного количества, что означает отсутствие дополнительных данных на сервере.
366
556
 
557
+ ### `isStartReached`. Определение начала списка
558
+
559
+ Флаг `isStartReached` будет установлен в `true`, если при `fetchMore({ direction: 'backward' })` сервер вернул меньше элементов, чем было запрошено.
560
+ Это означает, что более ранних данных больше нет, и повторные вызовы `fetchMore({ direction: 'backward' })` не будут запускать новые запросы.
561
+
367
562
  ### Изменение количества запрашиваемых записей
368
563
 
369
564
  Для изменения конфигурации InfiniteQuery необходимо использовать метод `createWithConfig`:
@@ -520,6 +715,9 @@ const docQueryWithCache = docsFetcher.queries.doc.createWithConfig(({ fetchPolic
520
715
  await docQueryWithCache.async(); // запрос не будет выполнен потому что прежде данные были получены с политикой `network-only` и записаны в кэш
521
716
  ```
522
717
 
718
+ Для `InfiniteQuery` параметры `initialOffset` и `initialCursor` позволяют при первом запросе нового инстанса начать загрузку с нужной позиции.
719
+ После `invalidate()` эти стартовые значения больше не применяются, и следующий запрос начинается с начала списка.
720
+
523
721
  ### Как работает кэш
524
722
 
525
723
  Все данные, возвращаемые `QuerySet` и `InfiniteQuerySet`, кэшируются в едином хранилище @astral/mobx-query.
@@ -716,6 +914,27 @@ docsFetcher.queries.document.createWithConfig({
716
914
  })
717
915
  ```
718
916
 
917
+ ## Последовательное получение данных
918
+
919
+ Для последовательного получения данных используйте флаг `enabledAutoFetch`.
920
+
921
+ ```ts
922
+ private get fileQuery() {
923
+ const fileId = this._documentStore.data?.FileId;
924
+
925
+ return this._docsFetcher.queries.file.createWithConfig(
926
+ {
927
+ enabledAutoFetch: Boolean(fileId),
928
+ },
929
+ fileId,
930
+ );
931
+ }
932
+
933
+ public get file() {
934
+ return this.fileQuery.data; // пока enabledAutoFetch==false, запроса данных не будет
935
+ }
936
+ ```
937
+
719
938
  ## Тестирование Fetcher на сонове QuerySet и InfiniteQuerySet.
720
939
 
721
940
  Для мокинга QuerySet и InfiniteQuerySet необходимо использовать mock следующего вида:
@@ -1037,6 +1256,10 @@ const createDocListInfiniteQuery = (filters: Omit<DocsDTO.DocListFilters, 'offse
1037
1256
  const docListQuery = createDocListInfiniteQuery({ search: 'test' });
1038
1257
  ```
1039
1258
 
1259
+ Executor `InfiniteQuery` получает объект `{ offset, count, cursor, direction }`.
1260
+ Если нужна только offset-пагинация, можно использовать только `offset` и `count`.
1261
+ `cursor` передается только при `fetchMore()` или при самом первом запросе, если задан `initialCursor`. В обычном первом запросе без `initialCursor` и после `invalidate()` значение `cursor` будет `undefined`.
1262
+
1040
1263
  #### Загрузка данных
1041
1264
 
1042
1265
  ```ts
@@ -1061,6 +1284,17 @@ await when(() => !query.isLoading);
1061
1284
  docListQuery.data.length; // 60 записей
1062
1285
  ```
1063
1286
 
1287
+ #### Статус дозагрузки `fetchMore`
1288
+
1289
+ - [Статус дозагрузки fetchMore](#статус-дозагрузки-fetchmore)
1290
+
1291
+ #### Дополнительные возможности
1292
+
1293
+ - [Старт не с начала списка](#старт-не-с-начала-списка)
1294
+ - [Запоминание последней успешной позиции](#запоминание-последней-успешной-позиции)
1295
+ - [Обратная дозагрузка данных](#обратная-дозагрузка-данных)
1296
+ - [Курсорная пагинация](#курсорная-пагинация)
1297
+
1064
1298
  #### `isEndReached`. Определение конца списка
1065
1299
 
1066
1300
  Флаг `isEndReached` будет установлен в `true`, если записи для загрузки закончились:
@@ -1090,6 +1324,10 @@ docListQuery.isEndReached; // true
1090
1324
 
1091
1325
  Флаг `isEndReached` устанавливается в `true`, когда количество полученных элементов меньше запрошенного количества, что означает отсутствие дополнительных данных на сервере.
1092
1326
 
1327
+ #### `isStartReached`. Определение начала списка
1328
+
1329
+ - [isStartReached. Определение начала списка](#isstartreached-определение-начала-списка)
1330
+
1093
1331
  #### Изменение количества запрашиваемых записей
1094
1332
 
1095
1333
  Для изменения конфигурации InfiniteQuery необходимо использовать третий параметр `config`:
@@ -1103,7 +1341,7 @@ const createDocListInfiniteQuery = (filters: Omit<DocsDTO.DocListFilters, 'offse
1103
1341
 
1104
1342
  #### Интерфейс InfiniteQueryConfig
1105
1343
  ```ts
1106
- export type InfiniteQueryConfig = {
1344
+ export type InfiniteQueryConfig<TResult = unknown> = {
1107
1345
  /**
1108
1346
  * Количество записей, которое будет загружено при первом и следующих запросах
1109
1347
  * @default 30
@@ -1121,6 +1359,15 @@ export type InfiniteQueryConfig = {
1121
1359
  * Политика кэширования данных.
1122
1360
  */
1123
1361
  fetchPolicy?: FetchPolicy;
1362
+ /**
1363
+ * Стартовое значение offset, от которого требуется сделать самый первый запрос.
1364
+ * @default 0
1365
+ */
1366
+ initialOffset?: number;
1367
+ /**
1368
+ * Стартовый элемент, от которого требуется сделать самый первый запрос.
1369
+ */
1370
+ initialCursor?: Partial<TResult>;
1124
1371
  /**
1125
1372
  * Режим фонового обновления
1126
1373
  * @default false
@@ -7,7 +7,7 @@ export type InfiniteQuerySetConfig = {
7
7
  };
8
8
  export type InfiniteQuerySetConfigurator<TParams extends any[], TResponse> = (...params: TParams) => {
9
9
  keys?: CacheKey[];
10
- execute: (infiniteParams: InfiniteParams) => Promise<TResponse[]>;
10
+ execute: (infiniteParams: InfiniteParams<TResponse>) => Promise<TResponse[]>;
11
11
  };
12
12
  /**
13
13
  * Набор infinite queries под одним ключем с целью повышения читаемости кода и удобства инвалидации по общему ключу
@@ -24,6 +24,10 @@ export declare class StatusStorage<TError> implements Statuses<TError> {
24
24
  */
25
25
  isSuccess: boolean;
26
26
  setStatues: (data: Statuses<TError>) => void;
27
+ setStartLoading: () => void;
28
+ setError: (error: TError) => void;
29
+ setSuccess: () => void;
30
+ setEndLoading: () => void;
27
31
  get statuses(): Statuses<TError>;
28
32
  }
29
33
  export declare class StatusStorageFactory extends StorageFactory<StatusStorage<any>> {
@@ -24,6 +24,24 @@ export class StatusStorage {
24
24
  this.error = data.error;
25
25
  this.isSuccess = data.isSuccess;
26
26
  };
27
+ this.setStartLoading = () => {
28
+ this.isLoading = true;
29
+ this.isError = false;
30
+ this.isSuccess = false;
31
+ };
32
+ this.setError = (error) => {
33
+ this.isSuccess = false;
34
+ this.isError = true;
35
+ this.error = error;
36
+ };
37
+ this.setSuccess = () => {
38
+ this.error = undefined;
39
+ this.isError = false;
40
+ this.isSuccess = true;
41
+ };
42
+ this.setEndLoading = () => {
43
+ this.isLoading = false;
44
+ };
27
45
  makeAutoObservable(this);
28
46
  }
29
47
  get statuses() {
@@ -88,6 +88,7 @@ export declare const createDocumentMock: () => {
88
88
  (eventInterface: "CloseEvent"): CloseEvent;
89
89
  (eventInterface: "CompositionEvent"): CompositionEvent;
90
90
  (eventInterface: "ContentVisibilityAutoStateChangeEvent"): ContentVisibilityAutoStateChangeEvent;
91
+ (eventInterface: "CookieChangeEvent"): CookieChangeEvent;
91
92
  (eventInterface: "CustomEvent"): CustomEvent;
92
93
  (eventInterface: "DeviceMotionEvent"): DeviceMotionEvent;
93
94
  (eventInterface: "DeviceOrientationEvent"): DeviceOrientationEvent;
@@ -173,7 +174,7 @@ export declare const createDocumentMock: () => {
173
174
  getSelection: (() => Selection | null) & import("vitest-mock-extended").CalledWithMock<Selection | null, []>;
174
175
  hasFocus: (() => boolean) & import("vitest-mock-extended").CalledWithMock<boolean, []>;
175
176
  hasStorageAccess: (() => Promise<boolean>) & import("vitest-mock-extended").CalledWithMock<Promise<boolean>, []>;
176
- importNode: (<T extends Node>(node: T, subtree?: boolean) => T) & import("vitest-mock-extended").CalledWithMock<Node, [node: Node, subtree?: boolean | undefined]>;
177
+ importNode: (<T extends Node>(node: T, options?: boolean | ImportNodeOptions) => T) & import("vitest-mock-extended").CalledWithMock<Node, [node: Node, options?: boolean | ImportNodeOptions | undefined]>;
177
178
  open: {
178
179
  (unused1?: string, unused2?: string): Document;
179
180
  (url: string | URL, name: string, features: string): WindowProxy | null;
@@ -185,9 +186,10 @@ export declare const createDocumentMock: () => {
185
186
  queryCommandValue: ((commandId: string) => string) & import("vitest-mock-extended").CalledWithMock<string, [commandId: string]>;
186
187
  releaseEvents: (() => void) & import("vitest-mock-extended").CalledWithMock<void, []>;
187
188
  requestStorageAccess: (() => Promise<void>) & import("vitest-mock-extended").CalledWithMock<Promise<void>, []>;
188
- startViewTransition: ((callbackOptions?: ViewTransitionUpdateCallback) => ViewTransition) & import("vitest-mock-extended").CalledWithMock<ViewTransition, [callbackOptions?: ViewTransitionUpdateCallback | undefined]>;
189
+ startViewTransition: ((callbackOptions?: ViewTransitionUpdateCallback | StartViewTransitionOptions) => ViewTransition) & import("vitest-mock-extended").CalledWithMock<ViewTransition, [callbackOptions?: ViewTransitionUpdateCallback | StartViewTransitionOptions | undefined]>;
189
190
  write: ((...text: string[]) => void) & import("vitest-mock-extended").CalledWithMock<void, string[]>;
190
191
  writeln: ((...text: string[]) => void) & import("vitest-mock-extended").CalledWithMock<void, string[]>;
192
+ readonly textContent: null;
191
193
  addEventListener: {
192
194
  <K extends keyof DocumentEventMap>(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
193
195
  (type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
@@ -208,7 +210,6 @@ export declare const createDocumentMock: () => {
208
210
  readonly parentElement: HTMLElement | null;
209
211
  readonly parentNode: ParentNode | null;
210
212
  readonly previousSibling: ChildNode | null;
211
- textContent: string | null;
212
213
  appendChild: (<T extends Node>(node: T) => T) & import("vitest-mock-extended").CalledWithMock<Node, [node: Node]>;
213
214
  cloneNode: ((subtree?: boolean) => Node) & import("vitest-mock-extended").CalledWithMock<Node, [subtree?: boolean | undefined]>;
214
215
  compareDocumentPosition: ((other: Node) => number) & import("vitest-mock-extended").CalledWithMock<number, [other: Node]>;
@@ -258,18 +259,19 @@ export declare const createDocumentMock: () => {
258
259
  onanimationend: ((this: GlobalEventHandlers, ev: AnimationEvent) => any) | null;
259
260
  onanimationiteration: ((this: GlobalEventHandlers, ev: AnimationEvent) => any) | null;
260
261
  onanimationstart: ((this: GlobalEventHandlers, ev: AnimationEvent) => any) | null;
261
- onauxclick: ((this: GlobalEventHandlers, ev: MouseEvent) => any) | null;
262
+ onauxclick: ((this: GlobalEventHandlers, ev: PointerEvent) => any) | null;
262
263
  onbeforeinput: ((this: GlobalEventHandlers, ev: InputEvent) => any) | null;
263
- onbeforetoggle: ((this: GlobalEventHandlers, ev: Event) => any) | null;
264
+ onbeforematch: ((this: GlobalEventHandlers, ev: Event) => any) | null;
265
+ onbeforetoggle: ((this: GlobalEventHandlers, ev: ToggleEvent) => any) | null;
264
266
  onblur: ((this: GlobalEventHandlers, ev: FocusEvent) => any) | null;
265
267
  oncancel: ((this: GlobalEventHandlers, ev: Event) => any) | null;
266
268
  oncanplay: ((this: GlobalEventHandlers, ev: Event) => any) | null;
267
269
  oncanplaythrough: ((this: GlobalEventHandlers, ev: Event) => any) | null;
268
270
  onchange: ((this: GlobalEventHandlers, ev: Event) => any) | null;
269
- onclick: ((this: GlobalEventHandlers, ev: MouseEvent) => any) | null;
271
+ onclick: ((this: GlobalEventHandlers, ev: PointerEvent) => any) | null;
270
272
  onclose: ((this: GlobalEventHandlers, ev: Event) => any) | null;
271
273
  oncontextlost: ((this: GlobalEventHandlers, ev: Event) => any) | null;
272
- oncontextmenu: ((this: GlobalEventHandlers, ev: MouseEvent) => any) | null;
274
+ oncontextmenu: ((this: GlobalEventHandlers, ev: PointerEvent) => any) | null;
273
275
  oncontextrestored: ((this: GlobalEventHandlers, ev: Event) => any) | null;
274
276
  oncopy: ((this: GlobalEventHandlers, ev: ClipboardEvent) => any) | null;
275
277
  oncuechange: ((this: GlobalEventHandlers, ev: Event) => any) | null;
@@ -317,6 +319,7 @@ export declare const createDocumentMock: () => {
317
319
  onpointermove: ((this: GlobalEventHandlers, ev: PointerEvent) => any) | null;
318
320
  onpointerout: ((this: GlobalEventHandlers, ev: PointerEvent) => any) | null;
319
321
  onpointerover: ((this: GlobalEventHandlers, ev: PointerEvent) => any) | null;
322
+ onpointerrawupdate: ((this: GlobalEventHandlers, ev: Event) => any) | null;
320
323
  onpointerup: ((this: GlobalEventHandlers, ev: PointerEvent) => any) | null;
321
324
  onprogress: ((this: GlobalEventHandlers, ev: ProgressEvent) => any) | null;
322
325
  onratechange: ((this: GlobalEventHandlers, ev: Event) => any) | null;
@@ -335,7 +338,7 @@ export declare const createDocumentMock: () => {
335
338
  onsubmit: ((this: GlobalEventHandlers, ev: SubmitEvent) => any) | null;
336
339
  onsuspend: ((this: GlobalEventHandlers, ev: Event) => any) | null;
337
340
  ontimeupdate: ((this: GlobalEventHandlers, ev: Event) => any) | null;
338
- ontoggle: ((this: GlobalEventHandlers, ev: Event) => any) | null;
341
+ ontoggle: ((this: GlobalEventHandlers, ev: ToggleEvent) => any) | null;
339
342
  ontouchcancel?: ((this: GlobalEventHandlers, ev: TouchEvent) => any) | null | undefined | undefined;
340
343
  ontouchend?: ((this: GlobalEventHandlers, ev: TouchEvent) => any) | null | undefined | undefined;
341
344
  ontouchmove?: ((this: GlobalEventHandlers, ev: TouchEvent) => any) | null | undefined | undefined;
@@ -31,22 +31,17 @@ export declare class AuxiliaryQuery<TResult, TError = void> {
31
31
  * для устранения гонки запросов
32
32
  */
33
33
  getUnifiedPromise: (executor: Executor<TResult>, onSuccess?: (data: TResult) => void) => Promise<TResult>;
34
- private setSuccess;
35
34
  private checkBackgroundAndSet;
36
35
  /**
37
36
  * Обработчик успешного ответа
38
37
  */
39
38
  submitSuccess: () => void;
40
- private setError;
41
- /**
42
- * Обработчик ошибки
43
- */
44
- submitError: (error: TError) => void;
45
- private setLoading;
39
+ private submitError;
46
40
  /**
47
41
  * Метод, вызываемый в самом начале запроса, чтобы сбросить флаги в соответствующее значение
48
42
  */
49
43
  startLoading: () => void;
44
+ private endLoading;
50
45
  /**
51
46
  * Метод для инвалидации данных
52
47
  */
@@ -41,19 +41,10 @@ class AuxiliaryQuery {
41
41
  });
42
42
  throw e;
43
43
  })
44
- .finally(() => {
45
- this.unifiedPromise = undefined;
46
- (0, mobx_1.runInAction)(() => {
47
- this.statusStorage.isLoading = false;
48
- });
49
- });
44
+ .finally(this.endLoading);
50
45
  }
51
46
  return this.unifiedPromise;
52
47
  };
53
- this.setSuccess = (storage) => {
54
- storage.isError = false;
55
- storage.isSuccess = true;
56
- };
57
48
  this.checkBackgroundAndSet = (setStorage) => {
58
49
  if (this.backgroundStatusStorage && this.statusStorage.isSuccess) {
59
50
  setStorage(this.backgroundStatusStorage);
@@ -66,32 +57,27 @@ class AuxiliaryQuery {
66
57
  * Обработчик успешного ответа
67
58
  */
68
59
  this.submitSuccess = () => {
69
- this.checkBackgroundAndSet(this.setSuccess);
60
+ this.checkBackgroundAndSet((storage) => storage.setSuccess());
70
61
  this.isInvalid = false;
71
62
  };
72
- this.setError = (storage, error) => {
73
- storage.isSuccess = false;
74
- storage.isError = true;
75
- storage.error = error;
76
- };
77
- /**
78
- * Обработчик ошибки
79
- */
80
63
  this.submitError = (error) => {
81
- this.checkBackgroundAndSet((storage) => this.setError(storage, error));
64
+ this.checkBackgroundAndSet((storage) => storage.setError(error));
82
65
  this.isInvalid = false;
83
66
  };
84
- this.setLoading = (storage) => {
85
- storage.isLoading = true;
86
- storage.isError = false;
87
- storage.isSuccess = false;
88
- };
89
67
  /**
90
68
  * Метод, вызываемый в самом начале запроса, чтобы сбросить флаги в соответствующее значение
91
69
  */
92
70
  this.startLoading = () => {
93
71
  this.isIdle = false;
94
- this.checkBackgroundAndSet(this.setLoading);
72
+ this.checkBackgroundAndSet((storage) => storage.setStartLoading());
73
+ };
74
+ this.endLoading = () => {
75
+ var _a;
76
+ this.unifiedPromise = undefined;
77
+ this.statusStorage.setEndLoading();
78
+ if (this.statusStorage.isSuccess) {
79
+ (_a = this.backgroundStatusStorage) === null || _a === void 0 ? void 0 : _a.setEndLoading();
80
+ }
95
81
  };
96
82
  /**
97
83
  * Метод для инвалидации данных
@@ -104,12 +90,10 @@ class AuxiliaryQuery {
104
90
  isIdle: mobx_1.observable,
105
91
  isInvalid: mobx_1.observable,
106
92
  submitSuccess: mobx_1.action,
107
- setSuccess: mobx_1.action,
108
- setError: mobx_1.action,
109
- setLoading: mobx_1.action,
110
93
  submitError: mobx_1.action,
111
94
  startLoading: mobx_1.action,
112
95
  invalidate: mobx_1.action,
96
+ endLoading: mobx_1.action,
113
97
  });
114
98
  }
115
99
  }