fix: Anify timeout logic running even when fetch resolved
Summary: Test Plan:
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
import { PromiseTimedOutError, promiseTimeout } from "~/libs/promiseTimeout";
|
||||||
import { sortByProperty } from "~/libs/sortByProperty";
|
import { sortByProperty } from "~/libs/sortByProperty";
|
||||||
|
|
||||||
import type { EpisodesResponse } from "./episode";
|
import type { EpisodesResponse } from "./episode";
|
||||||
@@ -11,22 +12,18 @@ export async function getEpisodesFromAnify(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let response: AnifyEpisodesResponse[] | null = null;
|
let response: AnifyEpisodesResponse[] | null = null;
|
||||||
try {
|
|
||||||
const abortController = new AbortController();
|
const abortController = new AbortController();
|
||||||
response = await Promise.race([
|
try {
|
||||||
|
response = await promiseTimeout(
|
||||||
fetch(`https://api.anify.tv/episodes/${aniListId}`, {
|
fetch(`https://api.anify.tv/episodes/${aniListId}`, {
|
||||||
signal: abortController.signal,
|
signal: abortController.signal,
|
||||||
}).then((res) => res.json<AnifyEpisodesResponse[]>()),
|
}).then((res) => res.json<AnifyEpisodesResponse[]>()),
|
||||||
// set a limit of 30 seconds
|
30 * 1000,
|
||||||
new Promise((resolve) => setTimeout(resolve, 30 * 1000)).then(() => {
|
|
||||||
abortController.abort("Loading episodes from Anify timed out");
|
|
||||||
console.error(
|
|
||||||
`Loading episodes from Anify timed out; aniListId: ${aniListId}`,
|
|
||||||
);
|
);
|
||||||
return null;
|
|
||||||
}),
|
|
||||||
]);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
if (e instanceof PromiseTimedOutError) {
|
||||||
|
abortController.abort("Loading episodes from Anify timed out");
|
||||||
|
}
|
||||||
console.error(
|
console.error(
|
||||||
new Error(
|
new Error(
|
||||||
`Error trying to load episodes from anify; aniListId: ${aniListId}`,
|
`Error trying to load episodes from anify; aniListId: ${aniListId}`,
|
||||||
|
|||||||
29
src/libs/promiseTimeout.spec.ts
Normal file
29
src/libs/promiseTimeout.spec.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { describe, expect, it } from "bun:test";
|
||||||
|
|
||||||
|
import { PromiseTimedOutError, promiseTimeout } from "./promiseTimeout";
|
||||||
|
|
||||||
|
describe("promiseTimeout", () => {
|
||||||
|
it("promise resolves within timeout, returns value", () => {
|
||||||
|
expect(
|
||||||
|
promiseTimeout(
|
||||||
|
wait(1).then(() => 2),
|
||||||
|
2,
|
||||||
|
),
|
||||||
|
).resolves.toBe(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("promise does not resolve within timeout, throws PromiseTimedOutError", () => {
|
||||||
|
expect(
|
||||||
|
promiseTimeout(
|
||||||
|
wait(2).then(() => 2),
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
).rejects.toThrow(PromiseTimedOutError);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function wait(ms: number) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(resolve, ms);
|
||||||
|
});
|
||||||
|
}
|
||||||
27
src/libs/promiseTimeout.ts
Normal file
27
src/libs/promiseTimeout.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
export function promiseTimeout<T>(
|
||||||
|
promise: Promise<T>,
|
||||||
|
timeoutMs: number,
|
||||||
|
): Promise<T | null> {
|
||||||
|
let hasPromiseResolved = false;
|
||||||
|
|
||||||
|
return Promise.race([
|
||||||
|
promise.then((value) => {
|
||||||
|
hasPromiseResolved = true;
|
||||||
|
return value;
|
||||||
|
}),
|
||||||
|
new Promise((resolve) => setTimeout(resolve, timeoutMs)).then(() => {
|
||||||
|
if (hasPromiseResolved) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new PromiseTimedOutError();
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PromiseTimedOutError extends Error {
|
||||||
|
constructor(message?: string) {
|
||||||
|
super(message ?? "Promise timed out");
|
||||||
|
this.name = "PromiseTimedOutError";
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user