LoginSignup
0
0

More than 3 years have passed since last update.

非同期処理の光と闇

Last updated at Posted at 2019-07-08

はじめに

今回の記事はNode.jsを使っている際に、非同期処理という便利な機能な弊害となったため、ここに解決策を書き記す。同じく悩む人に伝わってくれ。

非同期処理とは

まずはコードを見てもらおう。ローカルディレクトリのファイル情報を取得するための処理と同時に別の処理を行うと仮定したコードである。

sample.js
const fs = require('fs')

function hogehoge(){
    //ファイルを読み取る処理
    fs.readFile("<ファイルのパス>",
    function(error,data){//=処理Aと置く
        if(error)return -1;
        //終わったときに表示する
        console.log("ファイルの読み込みを完了しました!");
        console.log("データの中身は:" + data);
    }
}

function fugafuga(){//=処理Bとする
    console.log("fuga~");
}

function hogehoge();//ファイルの中身を出す。
function fugafuga();//fuga~と表示

この場合に表示されることが以下のときがある。

fuga~
ファイルの読み込みを完了しました!
データの中身は:うんたらかんたら

なんと、処理の順番が変わっている
処理A⇒処理Bとなるはずが、処理B⇒処理Aとなっているじゃないか。
これはファイル読み込みに時間がかかることを見越して、「ファイルを読み込む処理をすると同時にほかの処理も行う」という非同期処理がされているからだ。
うわぁ!なんて便利な機能なんだろう!!!
そう思うことだろう。
しかし、この機能には実は危険性があるのだ...

非同期処理の危険性

sample2.js
const fs = require('fs')

let filestr = "";

function hogehoge(){
    //ファイルを読み取る処理
    fs.readFile("<ファイルのパス>",
    function(error,data){
        if(error)return -1;
        filestr = "" + data;//fileの中身をfilestrに移す
        console.log("ファイルの読み込みを完了しました!");
    }
}

function fugafuga(){
    console.log("データの中身は:" + filestr);//filestrの中身を表示
}

function hogehoge();//ファイルを読み込んで
function fugafuga();//中身を表示

こうなった場合どうだろう?勘の鋭い方ならもうお気づきかもしれないが以下の通りになる可能性がある。

データ中身は:
ファイルの読み込みを完了しました!

「ちょい!ちょい!ちょい!ちょーい!!!」と思うだろう。そう、非同期処理の欠点として、同期処理でなければならない処理も非同期処理になってしまうということである。世に出されている便利な機能が非同期処理になっているというケースが少なくない。ではどう対応すればいいのだろうか。

くらえ!同期処理化アタック!!!

ならば、簡単だ。同期処理に戻してやればいい。
そこでPromiseという機能をつかおう。説明は省くがわかりやすいリンクを乗せておくので、ぜひ参考にしてくれ。
Promiseについて0から勉強してみた

出来上がったコードが以下の通りだ。

sample3.js
const fs = require('fs')

let filestr = "";

function hogehoge(){
    return new Promise(function(resolve,error){
        //ファイルを読み取る処理
        fs.readFile("<ファイルのパス>",
        function(error,data){
            if(error)return -1;

            filestr = "" + data;//fileの中身をfilestrに移す
            console.log("ファイルの読み込みを完了しました!");
            resolve(data)//処理が終わったらresolveでdataを返す。
        });
    }
}

function fugafuga(let str){
    console.log("データの中身は:" + filestr);//filestrの中身を表示
}

function hogehoge()//ファイルを読み込んで
.then(function(value){//ファイルが読み込み終わったら
    fugafuga(value);//中身を表示
}

こうすることで、非同期処理を同期処理にしてやることができる。やはり、同期処理が必要とされる場面が多くみられると思うので、Promiseは覚えておいて損はないだろう。

最後に

自分も理解したばかりでまだわからないことも多いので、ぜひ指摘をお願いしたいです。
間違えに気づいた方、改良点に気づいた方はぜひアドバイスをお願いします。

0
0
1

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