0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

レガシーなcallbackをpromisifyを使って書き直す

Last updated at Posted at 2023-06-11

こんにちは。@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してあげないと意図通りに動かないことがありる
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?