[Javascript] コールバック関数をpromiseで書き直してみる学習

2020年10月13日

Javascript テクノロジー プログラミング

eyecatch 毎日勉強、毎日精進がモットーの、下駄です。 新たなことを覚えるっていうのは、本当に楽しいことなんですね。 自分のできることが増えていくと、無限の可能性を感じることができます。 プログラミングって、そんな底なしの可能性が感じられて、もはやゲームをしている暇もないぐらい没頭できますね。 今回は、ES6対応のための、promiseについて、自分なりに深堀りしてみます。 ちなみに、promiseの詳細な説明は、色々なサイトで説明してくれているので、そちらで学んでくだされ。 https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise ここでは、promise関数を学習することと、古い書き方との違いを理解する事を目的にしています。

promiseは、非同期callbackを完結に書く方式

javascriptの旧タイプと大きく概念を覆してくれたのがこの、Promiseの存在でしょう。 ※個人的にですが・・・ これまで、コールバック関数をたくさん書いて、非同期処理の待ち処理に対応してきましたが、promiseは、それを完結に書けるということなので、どんな差があるのかを自分なりに書いて確かめてみた。 下記の基本HTMLに対して、文字を追記していく方式で試します。 const time1 = 2000; setTimeout(sync,time1); function sync(){ document.getElementById("text").value += "sync : "+ (+new Date()) +"\n"; } 2秒後に"sync : *time"という文字列が、HTMLに書き込まれます。 これに対して、promiseの同じ処理の書き方をすると、 const time2 = 1000; const wait = milliSeconds => new Promise(resolve => setTimeout(resolve, milliSeconds)); wait(time2).then(() => { document.getElementById("text").value += "promise : "+ (+new Date()) +"\n"; }); どうでしょう?これまでのcallback関数しか理解できていなかった、自分としては、意味不明なプログラムだったのですが、 setTimeout関数をwait関数にwrapして、それがthenという指定で非同期に対応してくれるというのが、このpromiseという機能のようです。 上記のプログラムは、できる限りシンプルに書いたケースですが、処理をまとめた関数などをpromise化しておくと、便利そうですね。 このpromiseは、処理の成功、失敗の判定や、繰り返し失敗した時に、便利に停止してくれる機能も備えているので、これまで膨らみがちだった書き方がもっとシンプルに書けるイメージは持てました。

prototypeの引き継ぎについて

実は個人的な関心は、javascript特有のprototypeでまとめた処理で無名関数でのやり取りに対応できるかどうかという点だったのですが、 要するにthisの引き継ぎがこれまでbindを使って行えてたのを、promiseもそういった処理に対応できるのかを調査したかったのです。 あまり、他のサイトにはそうした実践的な書き方をしているケースがなかったので、ライブラリの書き換えなどを躊躇してしまっていました。 const time3 = 3000; var FUNC1 = function(){ this.name = "sync-hoge"; this.set(time3); }; FUNC1.prototype.set = function(time){ setTimeout((function(e){this.sync(e)}).bind(this),time); }; FUNC1.prototype.sync = function(){ document.getElementById("text").value += this.name +" : "+ (+new Date()) +"\n"; }; new FUNC1(); FUNC1という定義された関数にprototypeで組み込まれた処理を数珠つなぎに実行していくコールバックサンプルです。 これをpromise方式で書くと、 const time4 = 2500; var FUNC2 = function(){ this.name = "promise-huga"; this.set(time4); }; FUNC2.prototype.wait = milliSeconds => new Promise(resolve => setTimeout(resolve, milliSeconds)); FUNC2.prototype.set = function(time){ this.wait(time).then(() => { document.getElementById("text").value += this.name +" : "+ (+new Date()) +"\n"; }); }; new FUNC2(); こんな感じですかね? あってます? でも、ちゃんと、promiseをFUNC2関数に埋め込んで、thisが引き継がれているのが確認できました。

まとめ

promise処理を使う時に、これまでのcallbackでのプログラムフロートかなり違ってくる間隔がよく分かったので、リファクタリングする事はできそうですが、こうやって書いてみても、あまりプログラム行数が減るという事は無いことがよく分かりました。 ただ、実際に、callbackが書けないようなプログラムの場合は、promiseを使うことで、簡易的に非同期チェックができるというメリットはあるでしょうね。 これにasync,awaitをさらに組み合わせてさらなる学習をしていかなければ・・・

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。