Nodejsでコールバックで処理する前提の非同期関数をプロミスオブジェクトを返す関数に変換する例
例えば、以下のような形で、asyncCallbackFunction
という関数の中でコールバックを受け取る非同期の関数fs.readFile
を実行することになったとします。
async function asyncCallbackFunction(path) { fs.readFile(path, 'utf-8', (err, data) => { if (err) { throw err; } console.log(`${path} is loaded!`); // #1 }); console.log('task finished!') // #2 } asyncCallbackFunction('/etc/passwd');
fs.readFile
関数は、非同期にコールバック処理をする関数です。上の例のコードでは、fs.readFile
は非同期に実行されるので、 このままでは、#2 => #1 の順番に実行されます。
もし、fs.readFileが、コールバック処理を省略するとPromiseオブジェクトを返す関数であれば、awaitを利用して以下のように書き換えることで、#1 => #2の順番で実行することができます。
async function asyncCallbackFunction(path) { try { const data = await fs.readFile(path, 'utf-8'); console.log(`${path} is loaded!`); // #1 } catch(err) { throw err; } console.log('task finished!') // #2 } asyncCallbackFunction('/etc/passwd');
しかし、これを実行すると、UnhandledPromiseRejectionWarning: TypeError [ERR_INVALID_CALLBACK]: Callback must be a function. Received 'utf-8'
というエラーが出てしまい、実行することができません。fs.readFile(path, 'utf-8')
では、promiseオブジェクトを返してくれないようです。
このような非同期のコールバック処理前提の関数を、async/awaitで処理できるようにするためには、以下のようにfs.readFile関数をpromiseオブジェクトを返すようにラップしてあげます。
function promiseReadFile(path, enc) { return new Promise((resolve, reject) => { fs.readFile(path, enc, (err, data) => { if(err) { reject(err); } resolve(data); }); }); }
promiseオブジェクトを返すpromiseReadFile
関数を利用することで、#1 => #2 の順番で処理を実行することが出来るようになりました。
async function asyncCallbackFunction(path) { try { const data = await promiseReadFile(path, 'utf-8'); console.log(`${path} is loaded!`); // #1 } catch(err) { throw err; } console.log('task finished!') // #2 } asyncCallbackFunction('/etc/passwd');