Node.jsを使った非同期処理の理解

皆さんこんにちは。
中野です。

今回は今までJavaやPHPなどを中心に触ってきて、非同期処理にあまり馴染みがないが、
JavaScriptベースでの開発を行うことになり、
ちょっとまだ非同期処理がわかんないなーというエンジニアの方を対象にした内容です。

問題を出します。
解答してみて下さい。
実際ソースを書いて、デバッグしてみて下さい。きっと理解が進みます。

準備

事前準備としてNode.jsをインストールして下さい。
また、以下のソースをワークフォルダに用意して下さい。
・main.js

main();

function main() { //この中身は書き換えてOK
    print_hello(); //このままだとうまくいかない
    print_world(); //このままだとうまくいかない
}

function print_hello() { //便宜上、非同期処理にしてある。引数や中身は書き換えてOK。
    setTimeout(() => {
        console.log('Hello,');
    }, 500);
}

function print_world() { //この中身は変更不可
    console.log('world!');
}

process.on("exit", () => {
    process.exit(0);
});

以下のコマンドで実行します。

node main.js

結果は…

world!
Hello,

となりました。これは、あかんです。

問題

問題1:call back 関数を使って、「Hello,」「world!」の順番で表示されるように修正せよ

call backがわからん!という方は、 頑張って調べて下さい。
こちらのサイトにはなかなか面白い感じで書いてありました。→https://nkmrkisk.com/archives/1157

問題2:Promise を使って、「Hello,」「world!」の順番で表示されるように修正せよ

Promiseがわからん!という方は、こちらを見て頂ければよいのではないでしょうか。→http://azu.github.io/promises-book/
よーく読んだら、答えもわかってしまうような気もしますが、それは目的が達せられたということで、良しとしましょう。

解答

正解は一つではありません。あくまでも、参考として載せます。
また、詳しい解説は載せません。
それよりも、実際動かしてみて、挙動を体感して下さい。
非同期処理はソースだけ見てても理解しづらいものです。

問題1の解答

main();

function main() {
    print_hello(
        print_world
    );
    
}

function print_hello(callback) {//引数にcallback関数を渡せるように修正
    setTimeout(() => {
        console.log('Hello,');
        callback();
    }, 500);
}

function print_world() { //この中身は変更不可
    console.log('world!');
}

process.on("exit", () => {
    process.exit(0);
});

問題2の解答

main();

function main() {
    print_hello().then(() => {
        print_world();
    }).catch((error) => {
        console.log(error);
    });
    
}

function print_hello() {//promiseを返却するように修正
    return new Promise( (resolve, reject) => {
        setTimeout(() => {
            console.log('Hello,');
            resolve();
        }, 500);
    });
}

function print_world() { //この中身は変更不可
    console.log('world!');
}

process.on("exit", () => {
    process.exit(0);
});

Promiseの理解を深めるため、print_hello()内のresolve()の記述を変更して

function print_hello() {
    return new Promise( (resolve, reject) => {
        setTimeout(() => {
            console.log('Hello,');
            reject('error!!');
        }, 500);
    });
}

として実行してみます。

Hello,
error!!

と表示されました。
reject(失敗)が呼ばれたことで、catch節に入ることが確認されました。
また、サンプルでは非同期処置は1つしか用意していませんが、
非同期処置を複数用意して同期的に呼ぶように変更を加えてみると、より理解が進むと思います。

JavaScriptベースの開発を進める上で、非同期処置は避けて通れない道です。
しかし、Promiseを使ってスッキリ書けるようになると、頭の中でも整理できるようになると思います。
では、今回はこの辺でー。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

2 × 4 =