diff --git a/platform/website/src/components/auth/auth-dialog.svelte b/platform/website/src/components/auth/auth-dialog.svelte index 5528275e7..a455a9b95 100644 --- a/platform/website/src/components/auth/auth-dialog.svelte +++ b/platform/website/src/components/auth/auth-dialog.svelte @@ -56,68 +56,65 @@ let usernameStatus: FieldStatus; let usernameValidationTimeout: number | NodeJS.Timeout; let rejectValidation: () => void; - function usernameValidate(v: string): Promise { - return new Promise((resolve, reject) => { - globalMessage = ""; - if ($authDialog === AuthDialog.Login) { - resolve({ type: FieldStatusType.Success }); - return; - } + async function usernameValidate(v: string): Promise { + globalMessage = ""; + if ($authDialog === AuthDialog.Login) { + return { type: FieldStatusType.Success }; + } - clearTimeout(usernameValidationTimeout); - if (rejectValidation) { - rejectValidation(); - } - rejectValidation = reject; + clearTimeout(usernameValidationTimeout); + if (rejectValidation) { + rejectValidation(); + } - const valid = z - .string() - .min(3, "Minimum of 3 characters") - .max(20, "Maximum of 20 characters") - .regex(/^[a-zA-Z0-9_]*$/, "Username can only contain letters, numbers, and underscores") - .safeParse(v); - if (!valid.success) { - resolve({ type: FieldStatusType.Error, message: valid.error.issues[0].message }); - return; - } + const valid = z + .string() + .min(3, "Minimum of 3 characters") + .max(20, "Maximum of 20 characters") + .regex(/^[a-zA-Z0-9_]*$/, "Username can only contain letters, numbers, and underscores") + .safeParse(v); + if (!valid.success) { + return { type: FieldStatusType.Error, message: valid.error.issues[0].message }; + } + + usernameStatus = { + type: FieldStatusType.Loading, + message: "Hold on while we check if this username is available...", + }; + + // Wait 500 milliseconds before checking the username. This prevents spamming the server with requests. + await new Promise((resolve, reject) => { + rejectValidation = reject; + usernameValidationTimeout = setTimeout(resolve, 500); + }); - usernameStatus = { - type: FieldStatusType.Loading, - message: "Hold on while we check if this username is available...", - }; - - usernameValidationTimeout = setTimeout(async () => { - const result = await client - .query( - graphql(` - query CheckUsername($username: String!) { - user { - user: byUsername(username: $username) { - id - } - } + const result = await client + .query( + graphql(` + query CheckUsername($username: String!) { + user { + user: byUsername(username: $username) { + id } - `), - { username: v }, - { - requestPolicy: "network-only", - }, - ) - .toPromise(); + } + } + `), + { username: v }, + { + requestPolicy: "network-only", + }, + ) + .toPromise(); - if (result.error) { - resolve({ type: FieldStatusType.Error, message: "Something went wrong." }); - return; - } + if (result.error) { + return { type: FieldStatusType.Error, message: "Something went wrong." }; + } - if (result.data?.user.user?.id) { - resolve({ type: FieldStatusType.Error, message: "This username is already taken" }); - return; - } + if (result.data?.user.user?.id) { + return { type: FieldStatusType.Error, message: "This username is already taken" }; + } - resolve({ type: FieldStatusType.Success }); - }, 500); - }); + return { type: FieldStatusType.Success }; } let emailStatus: FieldStatus; diff --git a/platform/website/src/components/form/field.svelte b/platform/website/src/components/form/field.svelte index 831d6a9e1..07b5e87fd 100644 --- a/platform/website/src/components/form/field.svelte +++ b/platform/website/src/components/form/field.svelte @@ -59,7 +59,14 @@ $: if (touched) { status = { type: FieldStatusType.Loading }; - validate(value).then((s) => (status = s)); + validate(value) + .then((s) => (status = s)) + .catch((e) => { + // Ignore rejected promises with no error + if (e) { + console.error(e); + } + }); }