【徹底解説】JavaScriptとNode.jsの非同期処理:async/awaitでスマートな開発を!
JavaScript、Node.jsにおける非同期関数からの値の返却:async/awaitを用いた方法
近年、Web開発において非同期処理がますます重要になってきています。非同期処理とは、プログラムが次の処理に移る前に、他の処理の完了を待機する処理を指します。JavaScriptとNode.jsでは、非同期処理を扱うための強力なツールとして、async/await
構文が提供されています。
本記事では、async/await
を用いて非同期関数から値を返却する方法について、わかりやすく解説します。
非同期関数は、async
キーワードを使用して宣言されます。この関数は、Promiseと呼ばれるオブジェクトを返します。Promiseは、非同期処理の結果を表すオブジェクトです。
非同期関数の内部では、await
キーワードを使用して、Promiseの完了を待つことができます。await
は、Promiseが解決されるまで処理をブロックします。Promiseが解決されると、その結果値がawait
式に格納されます。
非同期関数から値を返却するには、return
キーワードを使用します。返される値は、Promiseにラップされます。
以下に、非同期関数から値を返却する例を示します。
async function fetchData() {
const response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
const data = await response.json();
return data;
}
fetchData().then(data => {
console.log(data); // { id: 1, title: 'sunt aut facere repellat provident nihil', ... }
});
この例では、fetchData
関数は、https://jsonplaceholder.typicode.com/posts/1
からJSONデータを非同期に取得し、返却します。
エラー処理
非同期関数では、Promiseの拒否(reject)をキャッチしてエラー処理を行うこともできます。
以下に、エラー処理を行う例を示します。
async function fetchData() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
const data = await response.json();
return data;
} catch (error) {
console.error(error);
}
}
fetchData().then(data => {
console.log(data);
}).catch(error => {
console.error(error);
});
この例では、fetchData
関数は、エラーが発生した場合にcatch
ブロックで処理を行います。
async/await
は、JavaScriptとNode.jsにおける非同期処理を簡潔かつ効率的に扱うための強力なツールです。非同期関数からの値の返却とエラー処理について理解することで、より洗練されたかつ読みやすい非同期コードを書くことができます。
補足
- 本記事では、基本的な例のみを紹介しました。より複雑な非同期処理については、さらに深く学習する必要があります。
async/await
は、比較的新しい構文です。古いブラウザやNode.jsバージョンでは、対応していない場合があります。
非同期処理の連鎖
この例では、3つの非同期処理を連鎖的に実行します。
async function fetchData() {
const response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
const data = await response.json();
return data;
}
async function processData(data) {
const processedData = data.map(item => ({
id: item.id,
title: item.title.toUpperCase(),
}));
return processedData;
}
async function displayData(data) {
console.log(data);
}
fetchData()
.then(processData)
.then(displayData)
.catch(error => {
console.error(error);
});
このコードは、以下のように動作します。
processData
関数は、取得したJSONデータを加工します。displayData
関数は、加工されたデータをコンソールに出力します。
並列処理
async function fetchUser() {
const response = await fetch('https://jsonplaceholder.typicode.com/users/1');
const user = await response.json();
return user;
}
async function fetchPost() {
const response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
const post = await response.json();
return post;
}
(async () => {
const user = await fetchUser();
const post = await fetchPost();
console.log(user);
console.log(post);
})();
- 2つの非同期処理が完了したら、取得したデータそれぞれをコンソールに出力します。
エラー処理
この例では、非同期処理におけるエラー処理を実装します。
async function fetchData() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
const data = await response.json();
return data;
} catch (error) {
console.error(error);
return null;
}
}
async function main() {
const data = await fetchData();
if (data) {
console.log(data);
} else {
console.error('データの取得に失敗しました。');
}
}
main();
- 取得に失敗した場合、エラーメッセージを出力して
null
を返します。 main
関数は、fetchData
関数の結果を処理します。- データの取得が成功した場合、取得したデータをコンソールに出力します。
これらのサンプルコードは、async/await
を用いた非同期処理の基本的な使い方を理解するのに役立ちます。より複雑な非同期処理については、さらに深く学習する必要があります。
上記以外にも、async/await
を用いた様々な処理があります。ぜひ、自分自身で試しながら、使い方を身につけてください。
非同期処理における async/await 以外の選択肢
以下に、async/await
以外の代表的な非同期処理の選択肢と、それぞれの特徴を紹介します。
コールバック関数
最も伝統的な非同期処理の方法は、コールバック関数を使用する方法です。非同期処理を実行する関数に、完了時に呼び出されるコールバック関数を引数として渡します。
function fetchData(url, callback) {
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onload = function() {
if (xhr.status === 200) {
callback(null, JSON.parse(xhr.responseText));
} else {
callback(new Error('データの取得に失敗しました。'));
}
};
xhr.send();
}
fetchData('https://jsonplaceholder.typicode.com/posts/1', (error, data) => {
if (error) {
console.error(error);
} else {
console.log(data);
}
});
特徴:
- シンプルで理解しやすい
- 多くのライブラリやAPIで利用されている
欠点:
- ネストが深くなるとコードが読みづらくなる
- エラー処理が複雑になる
Promise は、非同期処理の結果を表すオブジェクトです。Promise を使用すると、コールバック関数よりも柔軟かつ簡潔な非同期処理を記述することができます。
fetch('https://jsonplaceholder.typicode.com/posts/1')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
- コールバック関数よりも読みやすく、コードがスッキリする
then
メソッドとcatch
メソッドを使用して、成功時と失敗時の処理を分離できる- Promise を連鎖させて、複雑な非同期処理を表現できる
async/await
と比べると、やや冗長な記述になる
Observable は、非同期処理のイベントストリームを表すオブジェクトです。Observable を使用すると、非同期処理の進行状況をリアルタイムに監視することができます。
const observable = Rx.Observable.create(observer => {
fetch('https://jsonplaceholder.typicode.com/posts/1')
.then(response => response.json())
.then(data => observer.onNext(data))
.catch(error => observer.onError(error));
});
observable.subscribe(
data => console.log(data),
error => console.error(error),
() => console.log('完了しました')
);
- 非同期処理の進行状況をリアルタイムに監視できる
- 複数のイベントリスナーを登録できる
- さまざまなライブラリと連携できる
- Observable 自体の理解が難しい
Generator は、イテレータオブジェクトを生成する関数です。Generator を使用すると、非同期処理をイテレーションすることができます。
async function* fetchData() {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
const data = await response.json();
for (const post of data) {
yield post;
}
}
const iterator = fetchData();
for (const post of iterator) {
console.log(post);
}
- 非同期処理をイテレーションできる
それぞれの方法には、それぞれの特徴と利点・欠点があります。状況に合わせて適切な方法を選択することが重要です。
javascript node.js asynchronous