導入
非同期処理は、現代のアプリケーション開発において不可欠な要素です。しかし、非同期処理に関する誤った実装は、予期せぬバグやパフォーマンスの低下を引き起こすことがあります。本記事では、TypeScriptを用いて非同期処理を扱う際のアンチパターンを掘り下げ、具体的な失敗例とその改善策を示します。
教科書レベルの解説(非同期処理)
重要な概念の整理
非同期処理は、主にコールバック、Promise、async/awaitの3つの方法で実現されます。コールバックはシンプルですが、ネストが深くなると可読性が低下します。Promiseは、非同期処理の結果を扱うための強力な手段ですが、エラーハンドリングが難しい場合があります。async/awaitは、Promiseの上に構築されており、直感的なコード記述を可能にします。
コード例(TypeScript)
async function fetchData(url: string): Promise {
const response = await fetch(url);
if (!response.ok) {
throw new Error('Network response was not ok');
}
return await response.text();
}
async function processData() {
try {
const data = await fetchData('https://example.com/data');
console.log(data);
} catch (error) {
console.error('Error fetching data:', error);
}
}
processData();
コードの行ごとの解説
async function fetchData(url: string): Promise– 非同期関数を定義し、URLを引数として受け取ります。{ const response = await fetch(url);– 指定されたURLからデータを取得します。ここで、fetchの結果を待つことができます。if (!response.ok) { throw new Error('Network response was not ok'); }– レスポンスが正常でない場合、エラーをスローします。return await response.text();– レスポンスのテキストを返します。async function processData() {– データを処理する別の非同期関数を定義します。const data = await fetchData('https://example.com/data');– データを取得し、待機します。console.log(data);– 取得したデータをコンソールに出力します。catch (error) { console.error('Error fetching data:', error); }– エラーハンドリングを行います。processData();– 非同期処理を開始します。
アンチパターン編
非同期処理における一般的なアンチパターンの一つは、コールバック地獄です。以下の例を見てみましょう。
function fetchDataWithCallback(url: string, callback: (data: string) => void) {
fetch(url)
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.text();
})
.then(data => {
callback(data);
})
.catch(error => {
console.error('Error fetching data:', error);
});
}
fetchDataWithCallback('https://example.com/data', (data) => {
console.log(data);
});
このコードは、fetchの結果をコールバックで処理していますが、ネストが深くなり可読性が低下します。また、エラーハンドリングが分散しているため、問題を追跡するのが難しくなります。
改善策としては、async/awaitを用いてコードをフラットに保つことが挙げられます。これにより、エラーハンドリングも一元化され、可読性が向上します。
まとめ
- 非同期処理は、コールバック、Promise、async/awaitのいずれかで実装可能。
- コールバック地獄を避けるため、async/awaitを活用して可読性を向上させる。
- エラーハンドリングは一元化し、問題の追跡を容易にする。