JavaScript をかなりの時間使ったことがある人なら、おそらく「コールバック地獄」に遭遇したことがあるでしょう。ネストされたコールバックが複雑に絡み合い、コードが読みにくくなり、保守もさらに難しくなります。しかし、良いニュースがあります。適切なツールとパターンを使用すれば、コールバック地獄を完全に回避し、クリーンで効率的な非同期コードを作成できます。その方法を見てみましょう。
Promise は、JavaScript で非同期操作を処理するためのより構造化された方法であり、深くネストされたコールバックを排除するのに役立ちます。関数を引数として渡してネストする代わりに、Promise を使用すると、.then() メソッドと .catch() メソッドを使用して操作を連鎖させることができます。これにより、コードが直線的に保たれ、非常に理解しやすくなります。
例:
// Callback hell example: doSomething(function(result) { doSomethingElse(result, function(newResult) { doThirdThing(newResult, function(finalResult) { console.log(finalResult); }); }); }); // Using Promises: doSomething() .then(result => doSomethingElse(result)) .then(newResult => doThirdThing(newResult)) .then(finalResult => console.log(finalResult)) .catch(error => console.error(error));
この Promise ベースのアプローチでは、各ステップが明確かつ直線的な方法で前のステップに続くため、コードの流れを追跡し、必要に応じてデバッグすることが容易になります。
Promise はネストされたコールバックをクリーンアップするのに最適ですが、複数の非同期アクションを処理する場合には依然として面倒に感じることがあります。 async を入力して待ちます。これらの最新の JavaScript 機能を使用すると、同期コードとほぼ同じように見える非同期コードを作成でき、可読性と保守性が向上します。
例:
async function handleAsyncTasks() { try { const result = await doSomething(); const newResult = await doSomethingElse(result); const finalResult = await doThirdThing(newResult); console.log(finalResult); } catch (error) { console.error('Error:', error); } } handleAsyncTasks();
async/await を使用すると、特に同期コードの作成に慣れている開発者にとって、より直感的な方法で Promise を処理できます。これにより、.then() チェーンの必要性がなくなり、コードが上から下まで単純に見えるようになります。
コールバック地獄を回避するためのもう 1 つの強力なテクニックは、大規模で複雑なタスクをより小さな再利用可能な関数に分割することです。このモジュール式のアプローチにより、読みやすさが向上するだけでなく、コードのデバッグと保守が容易になります。
たとえば、API からデータをフェッチして処理する必要がある場合、すべてを 1 つの大きな関数に記述する代わりに、次のように分割できます。
例:
async function fetchData() { const response = await fetch('https://api.example.com/data'); return await response.json(); } async function processData(data) { // Process your data here return data.map(item => item.name); } async function main() { try { const data = await fetchData(); const processedData = await processData(data); console.log('Processed Data:', processedData); } catch (error) { console.error('An error occurred:', error); } } main();
データのフェッチと処理を独自の関数に分離することで、コードはさらに読みやすく、保守しやすくなります。
非同期コードの大きな課題の 1 つはエラー処理です。深くネストされたコールバック構造では、エラーを適切にキャッチして処理するのが難しい場合があります。 Promise を使用すると、操作の最後に .catch() を連鎖させることができます。ただし、async/await を try-catch ブロックと組み合わせると、より自然で読みやすいエラー処理方法が提供されます。
例:
async function riskyOperation() { try { const result = await someAsyncTask(); console.log('Result:', result); } catch (error) { console.error('Something went wrong:', error); } } riskyOperation();
これにより、非同期コードの特定の部分内のエラーを捕捉し、コードを明確かつ管理しやすく保ち、エラーが気付かれないようにすることができます。
場合によっては、複数の非同期操作を同時に管理する必要があります。 Promise.all() は一般的に使用されますが、1 つの Promise が失敗すると実行を停止します。このような場合、Promise.allSettled() が役に立ちます。Promise.allSettled() は、すべての Promise が解決 (解決または拒否) するのを待って、その結果を返します。
例:
// Callback hell example: doSomething(function(result) { doSomethingElse(result, function(newResult) { doThirdThing(newResult, function(finalResult) { console.log(finalResult); }); }); }); // Using Promises: doSomething() .then(result => doSomethingElse(result)) .then(newResult => doThirdThing(newResult)) .then(finalResult => console.log(finalResult)) .catch(error => console.error(error));
画像処理やデータ処理など、CPU を大量に使用するタスクの場合、JavaScript のシングルスレッドの性質によりアプリケーションがフリーズする可能性があります。ここが Web Workers の強みです。Web Workers を使用すると、メイン スレッドをブロックすることなくバックグラウンドでタスクを実行でき、UI の応答性を維持できます。
例:
async function handleAsyncTasks() { try { const result = await doSomething(); const newResult = await doSomethingElse(result); const finalResult = await doThirdThing(newResult); console.log(finalResult); } catch (error) { console.error('Error:', error); } } handleAsyncTasks();
重いタスクを Web ワーカーにオフロードすることで、メイン スレッドは UI インタラクションやその他の重要な機能を自由に処理できるようになり、よりスムーズなユーザー エクスペリエンスが確保されます。
コールバック地獄を回避し、よりクリーンな非同期 JavaScript を作成することは、コードをより読みやすく、保守しやすく、効率的にすることにつながります。 Promises、async/await、コードのモジュール化、Web Workers の活用のいずれを使用している場合でも、目標は同じです。コードをフラットで整理した状態に保つことです。そうすれば、デバッグの悪夢から身を守るだけでなく、他の人 (あるいは将来のあなた!) に感謝されるコードを書くこともできます。
私のウェブサイト: https://Shafayet.zya.me
あなたのためのミームですか?
以上がコールバック地獄、よりクリーンな非同期 JavaScript の作成の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。