JavaScriptでコールバック地獄を脱出!プロミスでコードをスッキリさせよう
JavaScript、Node.js、コールバックにおける「既存のコールバック API をプロミスに変換する方法」
コールバック API は、非同期処理の結果を処理するために、関数への参照を渡す仕組みです。処理が完了すると、コールバック関数が呼び出され、結果を渡されます。
function myFunction(callback) {
// 非同期処理
setTimeout(() => {
const result = 10;
callback(result);
}, 1000);
}
myFunction((result) => {
// 結果処理
console.log(result); // 10
});
プロミスとは
プロミス は、非同期処理の完了を表現するオブジェクトです。resolve
と reject
という 2 つのメソッドを持ち、処理が成功した場合は resolve
、失敗した場合は reject
を呼び出すことで、結果を通知することができます。
const myPromise = new Promise((resolve, reject) => {
// 非同期処理
setTimeout(() => {
const result = 10;
resolve(result);
}, 1000);
});
myPromise.then((result) => {
// 成功時の処理
console.log(result); // 10
}).catch((error) => {
// 失敗時の処理
console.error(error);
});
既存のコールバック API をプロミスに変換するには、いくつかの方法があります。
自作でプロミスを作成する
以下のコードは、コールバック API を受け取り、プロミスを返す関数 promisify
の例です。
function promisify(callbackBasedApi) {
return function promisified() {
// 引数を配列に変換
const args = Array.from(arguments);
return new Promise((resolve, reject) => {
// コールバック関数を追加
args.push((err, result) => {
if (err) {
return reject(err);
}
resolve(result);
});
// 元の API を呼び出す
callbackBasedApi.apply(null, args);
});
};
}
ライブラリを使用する
bluebird
などのライブラリには、promisify
などの便利なヘルパー関数が含まれています。
const Promise = require('bluebird');
const promisifiedApi = Promise.promisify(callbackBasedApi);
promisifiedApi().then((result) => {
// 処理
});
コールバック API をプロミスに変換することで、非同期処理のコードをより簡潔で読みやすくすることができます。
メリット
- コードの可読性とメンテナンス性の向上
- エラー処理の簡略化
- async/await との連携
- すべての API がプロミスに対応しているわけではない
- ラッパー関数の作成が必要となる場合がある
自作でプロミスを作成する
function myFunction(callback) {
// 非同期処理
setTimeout(() => {
const result = 10;
callback(result);
}, 1000);
}
function promisify(callbackBasedApi) {
return function promisified() {
// 引数を配列に変換
const args = Array.from(arguments);
return new Promise((resolve, reject) => {
// コールバック関数を追加
args.push((err, result) => {
if (err) {
return reject(err);
}
resolve(result);
});
// 元の API を呼び出す
callbackBasedApi.apply(null, args);
});
};
}
const promisifiedMyFunction = promisify(myFunction);
promisifiedMyFunction().then((result) => {
// 処理
console.log(result); // 10
});
ライブラリを使用する
const Promise = require('bluebird');
function myFunction(callback) {
// 非同期処理
setTimeout(() => {
const result = 10;
callback(result);
}, 1000);
}
const promisifiedMyFunction = Promise.promisify(myFunction);
promisifiedMyFunction().then((result) => {
// 処理
console.log(result); // 10
});
async/await
を使用して、さらにコードを簡潔にすることができます。
async function main() {
const result = await promisifiedMyFunction();
console.log(result); // 10
}
main();
- エラー処理も忘れずに行いましょう。
async function main() {
try {
const result = await promisifiedMyFunction();
console.log(result); // 10
} catch (error) {
console.error(error);
}
}
main();
コールバック API をプロミスに変換する方法
自作でプロミスを作成する
Promise コンストラクタを使用する
function myFunction(callback) {
// 非同期処理
setTimeout(() => {
const result = 10;
callback(result);
}, 1000);
}
function promisify(callbackBasedApi) {
return new Promise((resolve, reject) => {
callbackBasedApi((err, result) => {
if (err) {
return reject(err);
}
resolve(result);
});
});
}
const promisifiedMyFunction = promisify(myFunction);
promisifiedMyFunction().then((result) => {
// 処理
console.log(result); // 10
});
async 関数を使用する
async function myFunction() {
// 非同期処理
const result = await new Promise((resolve) => {
setTimeout(() => {
resolve(10);
}, 1000);
});
return result;
}
const promisifiedMyFunction = myFunction;
promisifiedMyFunction().then((result) => {
// 処理
console.log(result); // 10
});
上記以外にも、様々なライブラリが存在します。
async function main() {
const result = await promisifiedMyFunction();
console.log(result); // 10
}
main();
async function main() {
try {
const result = await promisifiedMyFunction();
console.log(result); // 10
} catch (error) {
console.error(error);
}
}
main();
javascript node.js callback