async enhancement

71
Async Enhancement Grand-Frontend-Osaka 2015 Summer 2015.8.22

Upload: kamiyam-

Post on 17-Feb-2017

1.864 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: Async Enhancement

Async EnhancementGrand-Frontend-Osaka 2015 Summer

2015.8.22

Page 2: Async Enhancement

自己紹介• かみやん (Twitter@kamiyam)

http://nantokaworks.com

• 主にJavaScriptでお仕事をしている人

• カメラ/自動車

Engineer

Page 3: Async Enhancement

AGENDA• JavaScriptと非同期処理 • 非同期の強みと弱み • 非同期処理実行のエンドポイント • ライブラリコールバック • 非同期処理中のエラーハンドリング • 複数非同期処理のコールバック

Page 4: Async Enhancement

AGENDA• 非同期処理実行時のscopeのお話 • Promise • 革命的だった async モジュール • Promise準拠 • Q • まとめ

Page 5: Async Enhancement

JavaScriptと非同期処理

Page 6: Async Enhancement

同期処理

2sec

5sec

1sec

Page 7: Async Enhancement

同期処理

2sec

5sec

1sec

Page 8: Async Enhancement

2sec

5sec

非同期処理

1sec

Page 9: Async Enhancement

2sec

5sec

非同期処理

1sec

Page 10: Async Enhancement

非同期の強みと弱み

Page 11: Async Enhancement

// sorry node.js codevar fs = require(“fs”);

// Sync read directoryvar files = fs.readdirSync(“.”);console.log(files);console.log(“conmplate”);

// Async read directoryfs.readdir(“.", function(err, files){ if (err) throw err; console.log(files);});console.log(“complate…?”);

Page 12: Async Enhancement

プログラムのメインフローを邪魔せず非同期で処理をnon blockingで実行

(する代わりに人が追いにくい流れに)

Page 13: Async Enhancement

ドミノ倒しを想像するとわかりやすい

Page 14: Async Enhancement

非同期処理実行の エンドポイント

Page 15: Async Enhancement

// document ready$(function(){ var $target = $(".initAnimetion”); $target.fadeIn( "slow", function() { setTimeout(function(){ $target.fadeOut( "slow", function() { console.log( "completed!!!" ); }) }), 2*1000 ); //2秒待つ });});

Page 16: Async Enhancement

非同期の処理が終わった時に実行されるコールバック関数が必要

Page 17: Async Enhancement

ライブラリコールバック

Page 18: Async Enhancement

処理終了後の振る舞いは利用者に委ねなければならない=コールバック関数が常に必要

Page 19: Async Enhancement

// example(function($){$.mySuperElegantLibrary = (function(){var hoge = “”;var fuga = “”;return {miracleMethod: function(arg1,cb){if(typeof(arg1) === 'function') cb = arg1;if((cb == null)) cb = $.noop;

},specialMethod: function(arg1,cb){if(typeof(arg1) === 'function') cb = arg1;if((cb == null)) cb = $.noop;

}}

})();})(jQuery);

Page 20: Async Enhancement

変数 cb は関数なのか文字列なのかundefinedなのかそうじゃないのか…

Page 21: Async Enhancement

つきまとうコールバックとの闘い

Page 22: Async Enhancement

非同期処理中の エラーハンドリング

Page 23: Async Enhancement

JavaScript にも try…catch あります

Page 24: Async Enhancement

// example catching error(function(){try{

throw new Error("エラーです");

}catch(e){ console.log(e); console.log("ここで正しい処理をします")}

})();

Page 25: Async Enhancement

// example catching error…???// callback method inner is wonder land

(function(){try{ setTimeout(function(){ throw new Error("エラーです"); },1000);}catch(e){ console.log(e); console.log("ここでただしい処理をしますし(時間差)");}})();

Page 26: Async Enhancement

oh……

Page 27: Async Enhancement

複数非同期処理の コールバック

Page 28: Async Enhancement

// async methodsvar A = function(cb){ setTimeout(function(){ cb("1秒掛かる処理を実行しました"); },1000);};

var B = function(cb){ setTimeout(function(){ cb("5秒掛かる処理を実行しました"); },5000);};

var C = function(cb){ setTimeout(function(){ cb("2秒掛かる処理を実行しました"); },2000);};

Page 29: Async Enhancement

MISSION

処理A,B,C それぞれの結果をA,B,Cの順に配列に入れよ

Page 30: Async Enhancement

//oh! very easyvar result =[];

A(function(message1){

console.log(message1); result.push(message1);

B(function(message2){

console.log(message2); result.push(message2);

C(function(message3){

console.log(message3); result.push(message3); console.log("全ての処理がおわりました"); console.log(result); });

});});

Page 31: Async Enhancement

同期処理

2sec

5sec

1sec

Page 32: Async Enhancement

同期処理

2sec

5sec

1sec

Page 33: Async Enhancement

// parallelsvar allRequest = [A,B,C];var result =[];var counter = allRequest.length;

allRequest.forEach(function(request,i){

console.log(i); // 0,1,2 request(function(message){

// Message出力(単体) console.log(message); result[i] = message;

console.log(i); //0,2,1 <—-?

if(--counter == 0){ // Message出力(全体) console.log("全ての処理がおわりました"); console.log(result); }

});});

Page 34: Async Enhancement

2sec

5sec

非同期処理

1sec

Page 35: Async Enhancement

2sec

5sec

非同期処理

1sec

Page 36: Async Enhancement

直列同期処理処理内容 処理時間

処理①

処理②

処理③

完了

Page 37: Async Enhancement

直列同期処理処理内容 処理時間

処理①

処理②

処理③

※ 前述サンプルのような処理の結果を以って次の処理を行う場合は別

同時に実行出来る処理は実行してしまいたい完了

Page 38: Async Enhancement

並列同期処理処理内容 処理時間

処理①

処理②

処理③

完了

Page 39: Async Enhancement

並列同期処理処理内容 処理時間

処理①

処理②

処理③

完了

それぞれの処理を同時に実行し、一番遅い処理が完了するまで他は待機

Page 40: Async Enhancement

ここで一旦話は変わり…

Page 41: Async Enhancement

非同期処理実行時の scopeのお話

Page 42: Async Enhancement

JavaScript ループで回した時、最後の方の要素しかなんか動かない問題

Page 43: Async Enhancement

// no problem(function($){$(function(){

// display none $("#content").children().hide();

//forEach$("#content").children().each(function(i,item){

// show $(item).fadeIn("slow");

})

})

})(jQuery)

Page 44: Async Enhancement

// no problem(function($){ $(function(){

// display none $("#content").children().hide(); //forEach $("#content").children().each(function(i,item){ // show setTimeout(function(){ $(item).fadeIn("slow"); }, i * 1000);

})

})

})(jQuery)

Page 45: Async Enhancement

大丈夫そう

Page 46: Async Enhancement

// problems happen…// why!!! JavaScript looping!!(function($){ $(function(){

// display none $("#content").children().hide();

var children = $("#content").children(); for(var i=0; i < children.length; i++){ //for loop

// show setTimeout(function(){ var item = children[i]; $(item).fadeIn("slow"); }, i * 1000);

}

})

})(jQuery)

Page 47: Async Enhancement

// changing code…(function($){ $(function(){

// display none $(“#content”).children().hide(); var show = function(i){ // show setTimeout(function(){ var item = children[i]; $(item).fadeIn("slow"); }, i * 1000); }

var children = $("#content").children(); for(var i=0; i < children.length; i++){ //for loop show(i) }

})

})(jQuery)

Page 48: Async Enhancement

// before parallels processvar allRequest = [A,B,C];var result =[];var counter = allRequest.length;

for(var i=0; i<allRequest.length; i++){

console.log(i); // 0,1,2 allRequest[i](function(message){

// Message出力(単体) console.log(message); result[i] = message;

console.log(i); //3,3,3 <- !!!

if(--counter == 0){ // Message出力(全体) console.log("全ての処理がおわりました"); console.log(result); }

});}

Page 49: Async Enhancement

くろーじゃー…

Page 50: Async Enhancement

Promise

Page 51: Async Enhancement

複数の非同期処理の最後もうちょっとなんとかなりませんか?

Page 52: Async Enhancement

成功と失敗への遷移の確約

Page 53: Async Enhancement

Promises/A+https://promisesaplus.com/

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise

MDN Promise

http://caniuse.com/#feat=promises

Can I Use

Page 54: Async Enhancement

try~catchはエラーの確約だったはず…

Page 55: Async Enhancement

// promise…then…catchvar promise = new Promise(function(resolve,reject){// example async progressdoSomhing(function(error, data){if(error) return reject(error);resolve(data);})

});

promise.then(function(data){// with success}).catch(function(error){// fail…})

Page 56: Async Enhancement

// parallel…then…catchvar promise1 = new Promise(function(resolve,reject){

// example async progressdoSomhing(function(error, data1){if(error) return reject(error);resolve(data1);

})});

var promise2 = new Promise(function(resolve,reject){// 省略resolve(data2)

});

Promise.all([promise1,promise2]).then(function(result){// with successconsole.log(result); // [data1,data2]

}).catch(function(error){// fail…

})

Page 57: Async Enhancement

resolve / reject に結果の約束を結びつける

Page 58: Async Enhancement

革命的だった async モジュール(私の中では)

Page 59: Async Enhancement

async.waterfall([function(next){console.log(“1”);

setTimeout(function(){console.log(“1 complete”);next(null, 1); //next(error, result);

},3000);},function(next){console.log(“2”)

setTimeout(function(){console.log(“2 complete”);next(null, 2); //next(error, result);

},3000);}], function(err, result1, result2 ){console.log(err); // …nullconsole.log(result1); //…1console.log(result2); //…2

});

Page 60: Async Enhancement

async. parallel([function(callback){console.log(“1”);

setTimeout(function(){console.log(“1 complete”);callback(null, 1); //arg1…error,arg2….result

},3000);},function(next){console.log(“2”)

setTimeout(function(){console.log(“2 complete”);callback(null, 2);

},1000);}], function(err, result){console.log(err); // …nullconsole.log(result); //…[“1”,”2”]

});

Page 61: Async Enhancement

Promise準拠

Page 62: Async Enhancement

JavaScript Promises ※ 公開日 2013/12/16

http://www.html5rocks.com/ja/tutorials/es6/promises/

Conformant Implementationshttps://promisesaplus.com/implementations

Page 63: Async Enhancement

Q

Page 64: Async Enhancement

// promise…then…catchvar promise = function(){

var deferred = q.deferred();// example async progressdoSomething(function(error, data){if(error) return deferred.reject(error);deferred.resolve(data);

})return deferred.promise;

});

promise.then(function(result){// with successconsole.log(result); // data

}).catch(function(error){// fail…

})

Page 65: Async Enhancement

// parallel…then…catchvar promise1 = function(){

var deferred = q.deferred();// set deferred.reject(data1) & deferred.resolve(error)return deferred.promise;

});

var promise2 = function(){var deferred = q.deferred();// set deferred.reject(data2) & deferred.resolve(error)return deferred.promise;

});

q.all([promise1(), promise2()]).then(function(result){// with successconsole.log(result); // [data1,data2]

}).catch(function(error){// fail…

})

Page 66: Async Enhancement

まとまらないまとめ

Page 67: Async Enhancement

非同期処理が複数実行される時、その実行と完了を追うことが非常に重要

Page 68: Async Enhancement

Promise準拠ライブラリをうまく使い分けて半同期処理的なアプローチを

Page 69: Async Enhancement

他にGenerator / Yield もあるよ

Page 70: Async Enhancement

参考• JavaScriptと非同期のエラー処理 http://techblog.yahoo.co.jp/programming/javascript_error/

• あなたの知らない JavaScript Promise https://gist.github.com/kuu/e182d361520e70a158c9

• Effective ES6http://www.slideshare.net/teppeis/effective-es6

Page 71: Async Enhancement

ご清聴ありがとうございました