[JS/TS] 非同期のエラーハンドリング、あなたはどちら派?
Discussion
アンケート
お聞かせください!
JavaScript/TypeScript の非同期処理でのエラーハンドリングにおいて、あなたは try/catch (async/await)
or then/catch
のどちらを使うべきだとお考えですか?
良ければその理由もお教えいただけますと幸いです。
例) よくあるスライドショーのための React カスタムフックにて
try/catch
const useSlideshow = (query: string, interval: number) => {
const [url, setUrl] = useState(query);
useEffect(() => {
const timerId = setInterval(() => {
const effect = async () => {
try {
const res = await fetch(query);
if (document.startViewTransition) {
document.startViewTransition(() => setUrl(res.url));
} else {
setUrl(res.url);
}
} catch (err) {
console.error(`${err}`);
}
};
effect();
}, interval);
return () => {
clearInterval(timerId);
};
}, [interval, query]);
return [url] as const;
};
-
then/catch
(相違部分のみ抜粋)
const timerId = setInterval(() => {
fetch(query)
.then((res) => {
if (document.startViewTransition) {
document.startViewTransition(() => setUrl(res.url));
} else {
setUrl(res.url);
}
})
.catch((err) => {
console.error(`${err}`);
});
}, interval);
個人的には then/catch
の方が直感的に読めるような気がするのですが...
ちなみに Vitest でのカバレッジ差
ChatGPT さんがちゃっちゃと書いてくれたテスト(クリックで展開)
import "@testing-library/jest-dom";
import { act, render, screen } from "@testing-library/react";
import { useSlideshow } from "../useSlideshow";
vi.useFakeTimers();
const query = "https://unsplash.com/photos/bIhpiQA009k";
describe("useSlideshow", () => {
beforeEach(() => {
vi.clearAllTimers();
vi.clearAllMocks();
});
it("should update the url after specified interval", async () => {
const mockFetch = Promise.resolve({
url: query,
});
global.fetch = vi.fn().mockResolvedValueOnce(mockFetch);
function MockComponent() {
const [url] = useSlideshow(query, 1000);
return <div>{url}</div>;
}
render(<MockComponent />);
await act(async () => {
vi.advanceTimersByTime(1000);
});
expect(screen.getByText(query)).toBeInTheDocument();
});
it("should catch error and log it to the console", async () => {
const consoleSpy = vi.spyOn(console, "error");
global.fetch = vi.fn().mockRejectedValueOnce(new Error("Fetch error"));
function MockComponent() {
const [url] = useSlideshow(query, 1000);
return <div>{url}</div>;
}
render(<MockComponent />);
await act(async () => {
vi.advanceTimersByTime(1000);
});
expect(consoleSpy).toHaveBeenCalledWith("Error: Fetch error");
consoleSpy.mockRestore();
});
});
0