38
Hello Callback Hell. 2014/10/18 Miyazaki.js Satoshi Matsushita @satoshi_m8a

Hello Callback Hell : コールバック地獄の話

Embed Size (px)

DESCRIPTION

コールバック地獄の話

Citation preview

Page 1: Hello Callback Hell : コールバック地獄の話

Hello Callback Hell.2014/10/18 Miyazaki.js

Satoshi Matsushita @satoshi_m8a

Page 2: Hello Callback Hell : コールバック地獄の話

自己紹介名前:松下 聡史株式会社 アラタナ

出身:島根県松江市

趣味:読書、プログラミング、サーフィン、ネットサーフィン

主な出現場所:タリーズ宮崎高千穂通店

好きな言語:Scala, JavaScript

個人的な制作物:M+Web FONTS Subsetter : Play EC(EC-CUBEのクローン)

Page 3: Hello Callback Hell : コールバック地獄の話

何かのサービスを呼び出して、その結果を使って別のサービスを呼び出す。

Page 4: Hello Callback Hell : コールバック地獄の話

レジュメ

• コールバック関数が必要になる場面

• コールバック関数が多くなることの問題点(いわゆるコールバック地獄)

• $.Deferredの紹介

Page 5: Hello Callback Hell : コールバック地獄の話

例0

Page 6: Hello Callback Hell : コールバック地獄の話

ある数字にランダムな数字を加えて、計算過程を叫ぶ関数

! var getRandomInt = function (min, max) { return Math.floor(Math.random() * (max - min)) + min; }; ! var sayCalcProcess = function (a, b, result) { console.log('WRRRRYYYY ' + a + ' + ' + b + ' = ' + result); }; ! var sayRandomCalc = function (base) { var random = getRandomInt(0, 10); var result = base + random; sayCalcProcess(base, random, result); return result; }; ! sayRandomCalc(10);

Page 7: Hello Callback Hell : コールバック地獄の話

例1

Page 8: Hello Callback Hell : コールバック地獄の話

指定秒数遅れて、ある数字にランダムな数字を加えて、計算過程を叫び、結果を表示する関数

var sayRandomCalcDelay = function (params) { setTimeout(function () { var result = sayRandomCalc(params.base); params.success(result); }, params.delaySeconds * 1000); }; ! sayRandomCalcDelay({ base: 0, delaySeconds: 1, success: function (result) { console.log('final result is ' + result); } });

Page 9: Hello Callback Hell : コールバック地獄の話

• 何かのWebサービスを想定してもよい。

• $.ajax() $.get() $.post とかで呼び出す。

• 結果は遅れて返ってくる。

• 結果が返った時に実行する関数→コールバック関数

Page 10: Hello Callback Hell : コールバック地獄の話

例2

Page 11: Hello Callback Hell : コールバック地獄の話

指定秒数遅れて、ある数字にランダムな数字を加えて、その結果に指定秒数遅れてランダムな数字を加えて、計算過程を叫び、結果を表示する関数

sayRandomCalcDelay({ base: 0, delaySeconds: 1, success: function (result) { sayRandomCalcDelay({ base: result, delaySeconds: 2, success: function (result) { console.log('final result is ' + result); } }); } });

Page 12: Hello Callback Hell : コールバック地獄の話

例3

Page 13: Hello Callback Hell : コールバック地獄の話

関数化しよう function delay1(base) { sayRandomCalcDelay({ base: base, delaySeconds: 1, success: delay2 }); } ! function delay2(base) { sayRandomCalcDelay({ base: base, delaySeconds: 2, success: showResult }); } ! function showResult(result) { console.info('final result is ' + result); } !! delay1(0);

Page 14: Hello Callback Hell : コールバック地獄の話

例4

Page 15: Hello Callback Hell : コールバック地獄の話

まだ大丈夫。

function delay1(base) { sayRandomCalcDelay({ base: base, delaySeconds: 1, success: delay2 }); } ! function delay2(base) { sayRandomCalcDelay({ base: base, delaySeconds: 2, success: delay3 }); } ! function delay3(result) { sayRandomCalcDelay({ base: result, delaySeconds: 3, success: showResult }); } ! function showResult(result) { console.info('final result is ' + result); } !! delay1(0);

Page 16: Hello Callback Hell : コールバック地獄の話

ここで仕様変更

Page 17: Hello Callback Hell : コールバック地獄の話

計算結果が偶数ならsuccessコールバックを呼び、奇数ならerrorコールバックを呼ぶ

var sayRandomCalcDelay = function (params) { setTimeout(function () { var result = sayRandomCalc(params.base); if (result % 2 === 0) { params.success(result); } else { params.error(result); } }, params.delaySeconds * 1000); };

Page 18: Hello Callback Hell : コールバック地獄の話

例5

Page 19: Hello Callback Hell : コールバック地獄の話

お、おう

function delay1(base) { sayRandomCalcDelay({ base: base, delaySeconds: 1, success: delay2, error: onError }); } ! function delay2(base) { sayRandomCalcDelay({ base: base, delaySeconds: 2, success: delay3, error: onError }); } ! function delay3(base) { sayRandomCalcDelay({ base: base, delaySeconds: 3, success: showResult, error: onError }); }

function showResult(result) { console.info('final result is ' + result); } ! function onError(result) { console.error('error! ' + result + ' is odd number'); } ! delay1(0);

Page 20: Hello Callback Hell : コールバック地獄の話

また、仕様変更

Page 21: Hello Callback Hell : コールバック地獄の話

• delay1→delay2→delay3 の順番でしたが、

• delay3→delay2→delay1 の順番でも呼び出せるように。

Page 22: Hello Callback Hell : コールバック地獄の話

ぐはっ

function delay1(base) { sayRandomCalcDelay({ base: base, delaySeconds: 1, success: delay2, error: onError }); } ! function delay2(base) { sayRandomCalcDelay({ base: base, delaySeconds: 2, success: delay3, error: onError }); } ! function delay3(base) { sayRandomCalcDelay({ base: base, delaySeconds: 3, success: showResult, error: onError }); }

function showResult(result) { console.info('final result is ' + result); } ! function onError(result) { console.error('error! ' + result + ' is odd number'); } ! delay1(0);

Page 23: Hello Callback Hell : コールバック地獄の話

やりたいこと

• ある関数を呼び出し、計算が成功したら次の関数を呼び出し、最後まで成功したら、結果を表示する。

• 途中で計算が失敗したら、途中の計算を止めてエラーメッセージを表示する。

• 呼び出しの順番が入れ替わっても対応できる。

Page 24: Hello Callback Hell : コールバック地獄の話

jQuery.Deferred() を使って簡潔に表現する。

delay1(0) .then(delay2) .then(delay3) .then(showResult) .fail(onError);

Page 25: Hello Callback Hell : コールバック地獄の話

非同期関数をDeferredに対応させる

var sayRandomCalcAsync = function (params) { var d = new $.Deferred(); ! sayRandomCalcDelay({ base: params.base, success: function (result) { if (typeof params.success === 'function') { params.success(result); } d.resolve(result); }, error: function (result) { if (typeof params.error === 'function') { params.error(result); } d.reject(result); }, delaySeconds: params.delaySeconds }); ! return d.promise(); };

Deferredオブジェクトを生成

Promiseオブジェクトを返す

計算が成功したら、resolve関数に計算結果を引数にして呼び出す

計算が失敗したら、reject関数を呼び出す

Page 26: Hello Callback Hell : コールバック地獄の話

jQuery.Deferredに対応した関数は組み合わせ自由

delay3(0) .then(delay3) .then(delay1) .then(showResult) .fail(onError);

Page 27: Hello Callback Hell : コールバック地獄の話

jQuery 1.5~• jQuery 1.5 から$.ajax, $.get, $.post はDeferredに対応

$.ajax({ type: "POST", url: url, data: data, success: success, dataType: dataType });

return $.ajax({ type: "POST", url: url, data: data, dataType: dataType });

Page 28: Hello Callback Hell : コールバック地獄の話

jQuery.when()を使って複数のDeferredを組み合わせる

$.when(delay1(0), delay2(0)).done(function (a, b) { showResult(a + b); });

Page 29: Hello Callback Hell : コールバック地獄の話

参考

• 爆速でわかるjQuery.Deferred超入門 http://techblog.yahoo.co.jp/programming/jquery-deferred/

• Deferred Object | jQuery API Documentationhttp://api.jquery.com/category/deferred-object/

Page 30: Hello Callback Hell : コールバック地獄の話

こんなこともできます

delay1

delay3delay2

delay2 delay2

when

Page 31: Hello Callback Hell : コールバック地獄の話

何かに見えてきませんか?

Page 32: Hello Callback Hell : コールバック地獄の話

そうです、関数合成!!

Page 33: Hello Callback Hell : コールバック地獄の話

Michael Fogus 著、和田 祐一郎 訳

• 関数型言語ではない、JavaScriptで関数型プログラミングをする方法

• $.Deferredの紹介も少しある。

• 関数(パーツ)を組み合わせて、複雑な処理を簡単に記述できる。

• バグが発生しにくい。

• 発生しても直ぐに原因を特定できる。

• 変更に強い。

Page 34: Hello Callback Hell : コールバック地獄の話

すごいHaskellたのしく学ぼう!

やってます!

Page 35: Hello Callback Hell : コールバック地獄の話

Play Framework2(Scala)

Webアプリケーションも関数型で作る

Page 36: Hello Callback Hell : コールバック地獄の話

すみませんでした!!

Page 37: Hello Callback Hell : コールバック地獄の話
Page 38: Hello Callback Hell : コールバック地獄の話