Skip to content
Snippets Groups Projects
Commit 65486d06 authored by John Sparger's avatar John Sparger
Browse files

Maintain order of responses in useAsync

parent 95bed1a5
No related branches found
No related tags found
2 merge requests!139Merge before release,!117Maintain order of responses in useAsync
import React, { useCallback } from "react"; import React, { useCallback, useRef } from "react";
import SwaggerClient from 'swagger-client'; import SwaggerClient from 'swagger-client';
import { createContext, useContext, useEffect, useState } from "react"; import { createContext, useContext, useEffect, useState } from "react";
import { CircularProgress } from '@material-ui/core'; import { CircularProgress } from '@material-ui/core';
...@@ -49,7 +49,7 @@ export function UserProvider({ children }) { ...@@ -49,7 +49,7 @@ export function UserProvider({ children }) {
const resetLoginError = useCallback(() => setLoginError(null), [setLoginError]); const resetLoginError = useCallback(() => setLoginError(null), [setLoginError]);
console.log("rendering UserProvider") console.log("rendering UserProvider")
useEffect(getUser, [Boolean(loginResponse), getUser]); useEffect(getUser, [loginResponse, getUser]);
const logout = useCallback(async () => { const logout = useCallback(async () => {
console.log("Logging out!") console.log("Logging out!")
...@@ -57,11 +57,10 @@ export function UserProvider({ children }) { ...@@ -57,11 +57,10 @@ export function UserProvider({ children }) {
logoutFcn(); logoutFcn();
}, [resetUser, logoutFcn]) }, [resetUser, logoutFcn])
const login = useCallback(async (username, password) => { const login = useCallback((username, password) => {
console.log("Logging in!"); console.log("Logging in!");
await loginFcn(username, password); loginFcn(username, password);
getUser(); }, [loginFcn])
}, [loginFcn, getUser])
const createValue = useCallback(() => { const createValue = useCallback(() => {
return { user: user?.userInfo, userRoles: user?.userRoles, getUser, login, loginError, resetLoginError, logout }; return { user: user?.userInfo, userRoles: user?.userRoles, getUser, login, loginError, resetLoginError, logout };
...@@ -118,31 +117,63 @@ export function useAPIErrorHandler(onError) { ...@@ -118,31 +117,63 @@ export function useAPIErrorHandler(onError) {
return useCallback(errorHandler, [logout]); return useCallback(errorHandler, [logout]);
} }
export function useAsync({ fcn, call = true, init = null, onError = null }) { export function useQueuedResponse({ init = null, onError = null }) {
const queueRef = useRef([]);
const busyRef = useRef(false);
const [response, setResponse] = useState(init); const [response, setResponse] = useState(init);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const errorHandler = useAPIErrorHandler(onError); const errorHandler = useAPIErrorHandler(onError);
const MAX_QUEUE_LENGTH = 10;
const reset = useCallback(() => setResponse(init), [setResponse, init]); const processQueue = useCallback(
async () => {
if (busyRef.current) {
return;
}
const f = async (...args) => { busyRef.current = true;
try {
setLoading(true); setLoading(true);
const r = await fcn(...args);
console.log(r); let responses = [];
setResponse(r); const queue = queueRef.current;
} catch (e) { while (responses.length !== queue.length) {
console.warn(e); responses = await Promise.allSettled(queue);
errorHandler(e); }
queueRef.current = []
setLoading(false);
busyRef.current = false;
const { status, value, reason } = responses.pop();
if (status === "rejected") {
errorHandler(reason);
return;
}
setResponse(value);
}, [errorHandler])
const enqueue = useCallback((promise) => {
if (queueRef.current.length > MAX_QUEUE_LENGTH) {
throw new Error(`Max queue length (${MAX_QUEUE_LENGTH}) exceeded in useQueuedResponse.`)
} }
setLoading(false); queueRef.current.push(promise);
}; processQueue();
}, [queueRef, processQueue])
return { response, setResponse, loading, enqueue };
}
export function useAsync({ fcn, call = true, init = null, onError = null }) {
const { response, setResponse, loading, enqueue } = useQueuedResponse({ init, onError });
const reset = useCallback(() => setResponse(init), [setResponse, init]);
const wrapper = useCallback(f, [fcn, setResponse, setLoading, errorHandler]); const wrapper = useCallback((...args) => {
// const [loading, lwrapper] = useLoading(wrapper, response); enqueue(fcn(...args));
}, [fcn, enqueue]);
useEffect(() => { useEffect(() => {
console.log("i'm callin");
if (call) wrapper(); if (call) wrapper();
}, [wrapper, call]); }, [wrapper, call]);
......
...@@ -35,14 +35,16 @@ function AwSnap({ error, resetErrorBoundary }) { ...@@ -35,14 +35,16 @@ function AwSnap({ error, resetErrorBoundary }) {
function WindowErrorRedirect({ children }) { function WindowErrorRedirect({ children }) {
const handleError = useErrorHandler(); const handleError = useErrorHandler();
const wtf = useCallback((event) => { const onError = useCallback((event) => {
handleError(event.error); handleError(event.error ?? event.reason);
}, [handleError]); }, [handleError]);
useEffectOnMount(() => { useEffectOnMount(() => {
window.addEventListener('error', wtf); window.addEventListener('error', onError);
window.addEventListener('unhandledrejection', onError);
return function cleanup() { return function cleanup() {
window.removeEventListener('error', wtf); window.removeEventListener('error', onError);
window.removeEventListener('unhandledrejection', onError);
} }
}) })
...@@ -54,10 +56,7 @@ export function AppErrorBoundary({ children }) { ...@@ -54,10 +56,7 @@ export function AppErrorBoundary({ children }) {
<ErrorBoundary <ErrorBoundary
FallbackComponent={AwSnap} FallbackComponent={AwSnap}
onReset={() => { onReset={() => {
const reload = window.confirm("The application will reload");
if (reload) {
window.location.href = "/"; window.location.href = "/";
}
}} }}
> >
<WindowErrorRedirect> <WindowErrorRedirect>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment