impr: add promiseWithResolvers util

makes it a bit nicer when working with promises that need to be resolved outside of the promise body

!nuf
This commit is contained in:
Miodec 2025-04-11 16:53:47 +02:00
parent a7f4dcf9e0
commit e436671a45
4 changed files with 35 additions and 21 deletions

View file

@ -18,6 +18,7 @@ import {
import {
isDevEnvironment,
isObject,
promiseWithResolvers,
reloadAfter,
typedKeys,
} from "./utils/misc";
@ -44,8 +45,6 @@ const configLS = new LocalStorageWithSchema({
},
});
let loadDone: (value?: unknown) => void;
const config = {
...getDefaultConfig(),
};
@ -2125,8 +2124,7 @@ export function getConfigChanges(): Partial<Config> {
return configChanges;
}
export const loadPromise = new Promise((v) => {
loadDone = v;
});
const { promise: loadPromise, resolve: loadDone } = promiseWithResolvers();
export { loadPromise };
export default config;

View file

@ -1,26 +1,23 @@
import * as CaptchaController from "../controllers/captcha-controller";
import AnimatedModal from "../utils/animated-modal";
import { promiseWithResolvers } from "../utils/misc";
let resolvePromise: (token?: string) => void;
let { promise, resolve } = promiseWithResolvers<string | undefined>();
export let promise = new Promise<string | undefined>((resolve) => {
resolvePromise = resolve;
});
export { promise };
export async function show(): Promise<void> {
await modal.show({
mode: "dialog",
beforeAnimation: async (modal) => {
promise = new Promise((resolve) => {
resolvePromise = resolve;
});
({ promise, resolve } = promiseWithResolvers<string | undefined>());
CaptchaController.reset("register");
CaptchaController.render(
modal.querySelector(".g-recaptcha") as HTMLElement,
"register",
(token) => {
resolvePromise(token);
resolve(token);
hide();
}
);
@ -29,7 +26,7 @@ export async function show(): Promise<void> {
}
function hide(resolveToUndefined = false): void {
if (resolveToUndefined) resolvePromise();
if (resolveToUndefined) resolve(undefined);
void modal.hide();
}

View file

@ -197,7 +197,6 @@ export let activeWordElementOffset = 0;
export let resultVisible = false;
export let activeWordTop = 0;
export let testRestarting = false;
export let testRestartingPromise: Promise<unknown>;
export let lineTransition = false;
export let currentTestLine = 0;
export let resultCalculating = false;
@ -214,16 +213,18 @@ export function setActiveWordTop(val: number): void {
activeWordTop = val;
}
let restartingResolve: null | ((value?: unknown) => void);
let { promise: testRestartingPromise, resolve: restartingResolve } =
Misc.promiseWithResolvers();
export { testRestartingPromise };
export function setTestRestarting(val: boolean): void {
testRestarting = val;
if (val) {
testRestartingPromise = new Promise((resolve) => {
restartingResolve = resolve;
});
({ promise: testRestartingPromise, resolve: restartingResolve } =
Misc.promiseWithResolvers());
} else {
if (restartingResolve) restartingResolve();
restartingResolve = null;
restartingResolve();
}
}

View file

@ -693,4 +693,22 @@ export function applyReducedMotion(animationTime: number): number {
return prefersReducedMotion() ? 0 : animationTime;
}
/**
* Creates a promise with resolvers.
* This is useful for creating a promise that can be resolved or rejected from outside the promise itself.
*/
export function promiseWithResolvers<T = void>(): {
resolve: (value: T) => void;
reject: (reason?: unknown) => void;
promise: Promise<T>;
} {
let resolve!: (value: T) => void;
let reject!: (reason?: unknown) => void;
const promise = new Promise<T>((res, rej) => {
resolve = res;
reject = rej;
});
return { resolve, reject, promise };
}
// DO NOT ALTER GLOBAL OBJECTSONSTRUCTOR, IT WILL BREAK RESULT HASHES