dev: avoid double requests

Massimo Melina committed Sep 12, 2023 at 22:57 UTC 51825a7edbe10b2196202a9638f45c75533e3166
1 file changed +7 -5
shared/api.ts
+7 -5
@@ -2,7 +2,7 @@
2
3 import _ from 'lodash';
4 import { useCallback, useEffect, useRef } from 'react';
5 -import { Dict, Falsy, getPrefixUrl, pendingPromise, useStateMounted } from '.'
5 +import { Dict, Falsy, getPrefixUrl, pendingPromise, useStateMounted, wait } from '.'
6
7 export const API_URL = '/~/api/'
8
@@ -74,19 +74,21 @@ export function useApi<T=any>(cmd: string | Falsy, params?: object) {
74 const [forcer, setForcer] = useStateMounted(0)
75 const loadingRef = useRef<ReturnType<typeof apiCall>>()
76 const reloadingRef = useRef<any>()
77 - useEffect(()=>{
77 + useEffect(() => {
78 loadingRef.current?.abort()
79 setData(undefined)
80 setError(undefined)
81 if (!cmd) return
82 let aborted = false
83 - const req = apiCall<T>(cmd, params)
84 - const wholePromise = req.then(x => aborted || setData(x), x => aborted || setError(x))
83 + let req: undefined | ReturnType<typeof apiCall>
84 + const wholePromise = wait(0) // postpone a bit, so that if it is aborted immediately, it is never really fired (happens mostly in dev mode)
85 + .then(() => aborted ? undefined : req = apiCall<T>(cmd, params))
86 + .then(res => aborted || setData(res), err => aborted || setError(err))
87 .finally(() => loadingRef.current = reloadingRef.current = undefined)
88 loadingRef.current = Object.assign(wholePromise, {
89 abort() {
90 aborted = true
89 - req.abort()
91 + req?.abort()
92 }
93 })
94 reloadingRef.current?.resolve(wholePromise)