こんにちは。@Esperna です。
背景
レガシーなcallbackをasync/awaitで書き直すを書いた後にpromisifyというものがあることを教えてもらったので、今回も車輪の再発明ながらいじってみました。
callbackのコード例(再掲)
callback.js
function asyncTask(callback) {
const TIMEOUT = 10;
setTimeout(() => {
var data = 0;
if (Math.random() > 0.5) {
data = 1;
callback(null, data);
} else {
callback(new Error("Invalid Data"), data);
}
}, TIMEOUT);
}
asyncTask((err, data) => {
if (err === null) {
console.log(`successfully finished task. Data: ${data}`);
} else {
console.error(`error occured: ${err}: ${data}`);
}
});
console.log("called asyncTask");
Promise, async/awaitを使った例(再掲)
async_await2.js
function asyncTask() {
return new Promise((resolve, reject) => {
const TIMEOUT = 10;
setTimeout(() => {
var data = 0;
if (Math.random() > 0.5) {
data = 1;
resolve(data);
} else {
reject(new Error(`Invalid Data: ${data}`));
}
}, TIMEOUT);
});
}
async function doAsyncTask() {
try {
const data = await asyncTask();
console.log(`successfully finished task. Data: ${data}`);
} catch (err) {
console.error(`error occured: ${err}`);
}
}
doAsyncTask();
console.log("called asyncTask");
promisifyを使って書いてみた例
asyncTask_promisify.js
const util = require("util");
function _asyncTask(callback) {
const TIMEOUT = 10;
setTimeout(() => {
var data = 0;
if (Math.random() > 0.5) {
data = 1;
callback(null, data);
} else {
callback(new Error("Invalid Data"), data);
}
}, TIMEOUT);
}
async function doAsyncTask() {
const asyncTask = util.promisify(_asyncTask);
try {
const data = await asyncTask();
console.log(`successfully finished task. Data: ${data}`);
} catch (err) {
console.error(`error occured: ${err}`);
}
}
doAsyncTask();
console.log("called asyncTask");
所感
- new Promise((resolve, reject)をreturnする部分を書かなくて楽ということですね
- promisifyを知らないと読みづらいのかも
- これまでのお勉強でcallback hellは回避できるようになった気がする
promisifyを使う時の注意事項
- promisifyに渡す関数がerror-first callbackになっていること
- classのメソッドをpromisifyに渡すときはクラスのインスタンスをbindしてあげないと意図通りに動かないことがありる