SlideShare a Scribd company logo
リアルタイムアクションゲームから見る
Node.js 実践非同期処理
2015/05/19
DaikiTaniguchi (@kidach1)
Akatsuki inc.
kidach1
・Github https://github.com/kidach1
・Twitter https://twitter.com/kidach1
・Qiita http://qiita.com/kidach1
・Node / JavaScript /TypeScript
 Ruby / Rails
 Dvorak Keyboard
Agenda
・何を作っているか
・Nodeにおける非同期処理手法
 ・Promise
 ・Generator
・非同期処理実践
・テスト
Products
・2D横スクロールアクション
・マルチプレイ
 ・4人同時対戦
 ・座標同期型
 ・プレイヤーマッチング (Rating / Keyword)
Architecture
Sequence (rough)
Platform / Protocal / Language
・Node.js
・WebSocket
・JavaScript /TypeScript
Node.js
・SingleThread
・Non-blacking
・EventDriven
Node.js
・SingleThread
・Non-blacking
・EventDriven
→ websocket(双方向通信)との相性 ◎
Node.js
Node.js
Callback Hell
Solution
最近のjs非同期処理 PromiseとGeneratorの共存
http://qiita.com/kidach1/items/d997df84a0ede39d76ad
Promise
・非同期処理と操作を抽象化したAPI
・then chain
 ・thenable
・もともと初期のNodeには実装されていた
 →deprecated
 →ブラウザ ( jQuery.Deffered() )
 →ES6でPromiseA+として復活
・ES6系機能は--harmony optionが必要(v0.12)
  Node.jsのv0.12の時に harmony はdefaultにならないという結論になりました。 - from scratch
  http://yosuke-furukawa.hatenablog.com/entry/2014/01/31/153207
Promise
・ある非同期処理
Promise
・Promiseオブジェクトでくるむ
・基本呼び出し
Promise
・基本呼び出し
$ time node --harmony promise.js
Sync 1
Async 1
# node --harmony promise.js 0.05s user 0.05s system 8% cpu 1.179 total
Promise
・直列処理
Promise
・直列処理
$ time node --harmony promise.js
Sync 1
Sync 2
Sync 3
# node --harmony promise.js 0.06s user 0.06s system 3% cpu 3.218 total
Promise
・直列処理
$ time node --harmony promise.js
Sync 1
Sync 2
Sync 3
# node --harmony promise.js 0.06s user 0.06s system 3% cpu 3.218 total
Promise
・並列処理
Promise
・並列処理
$ time node --harmony promise.js
Sync 1
[ ‘Async 1’, ‘Async 2’, ‘Async 3’ ]
# node --harmony promise.js 0.07s user 0.03s system 8% cpu 1.079 total
Promise
・並列処理
$ time node --harmony promise.js
Sync 1
[ ‘Async 1’, ‘Async 2’, ‘Async 3’ ]
# node --harmony promise.js 0.07s user 0.03s system 8% cpu 1.079 total
Promise
Generator
・ES6
・co-routine
・非同期処理を同期処理っぽく(縦に)書く
・yeild/next で処理の中断/再開
 ・yeildables
・try~catch
Generator
・yeild/next
 ・処理の中断/再開
 ・値の送信/受信
Generator
・yeild/next
 ・処理の中断/再開
 ・値の送信/受信
$ time node --harmony generator.js
Sync 1
Async 1
Async 2
Async 3
# node --harmony generator.js 0.07s user 0.03s system 2% cpu 3.099 total
Generator
・yeild/next
 ・処理の中断/再開
 ・値の送信/受信
$ time node --harmony generator.js
Sync 1
Async 1
Async 2
Async 3
# node --harmony generator.js 0.07s user 0.03s system 2% cpu 3.099 total
・縦に書けて良い!が・・・
 ・送信/受信(next / yield)を るのは辛い
 ・generatorオブジェクトを隠 したい
Generator
co
https://github.com/tj/co
co
https://github.com/tj/co
Generator
Generator
Generator
・yieldに渡すメソッドのインターフェースは?
co
https://github.com/tj/co
co
https://github.com/tj/co
thenable is yieldables.
・直列処理
Generator with co
・直列処理
Generator with co
$ time node --harmony generator.js
Sync 1
Async 1
Async 2
Async 3
# node --harmony generator.js 0.06s user 0.02s system 2% cpu 3.081 total
・直列処理
Generator with co
・直列処理
Generator with co
$ time node --harmony generator.js
Sync
aSyNc
ASYNC
async
# node --harmony generator.js 0.07s user 0.02s system 2% cpu 3.074 total
・Error Handling
Generator
・Error Handling
Generator
・Error Handling
$ time node --harmony generator.js
Sync 1
Error: err!
# node --harmony generator.js 0.08s user 0.03s system 10% cpu 1.103 total
Generator
・Error Handling
Promise
・Error Handling
$ time node --harmony promise.js
Sync 1
Error: err!
# node --harmony promise.js 0.07s user 0.03s system 8% cpu 1.076 total
Promise
非同期処理実例
- ユーザー情報のセット
- レーティングごとまたは指定ルームNoごとのユーザー一覧の更新
- 同一ルームNoのユーザー/レートの近いユーザー(候補者)の取得
- 候補者からマッチング相手の絞込み
- マッチングしたことを各ユーザーに通知
・プレイヤーマッチング処理 (Promise ver)
Examples
Examples
・プレイヤーマッチング処理 (callback ver)
・プレイヤーマッチング処理 (Promise ver)
Examples
・プレイヤーマッチング処理 (Promise ver)
Examples
・Promise objcet
Examples
・プレイヤーマッチング処理 (Generator ver)
Examples
・プレイヤーマッチング処理 (Promise ver)
Examples
- roomに終了済ユーザー情報をセット
- 全員終了済かどうか判定
- 終了済ならroomに通知
・ゲーム終了判定処理
Examples
・ゲーム終了判定処理 (Promise ver)
Examples
・ゲーム終了判定処理 (Generator ver)
Examples
- socket.idからユーザー情報/ルーム情報を取得
- ルーム情報からルームメンバーを取得
- メンバーにdisconnectを通知
- ルーム情報からユーザー情報を除去
・プレイヤーdisconnect時の処理
Examples
・プレイヤーdisconnect時の処理 (Promise ver)
Examples
・プレイヤーdisconnect時の処理 (Promise ver)
Examples
・プレイヤーdisconnect時の処理 (Generator ver)
Examples
非同期処理のテスト
Testing
・接続シーケンスのシミュレート
・Mocha / should http://mochajs.org/
 ・高機能TestingFW & matcher
・sinon http://sinonjs.org/
 ・mock, stub
・CONNECTの後にCONNECTEDが返却されること
Testing
・discoonectが同一ルームのメンバーに通知されること
Testing
・discoonectが同一ルームのメンバーに通知されること
Testing
・discoonectが同一ルームのメンバーに通知されること
Testing
Testing
・discoonectが別ルームのメンバーに通知されないこと
Testing
・discoonectが別ルームのメンバーに通知されないこと
Testing
・discoonectが別ルームのメンバーに通知されないこと
・Client Class
Testing
まとめ
・thenable is yieldables
 ・個々の処理はPromiseベースでくるんでおき
 ・Promiseで事足りるならそのまま
 ・複雑性が増しそうならgeneratorの世界を訪れる
まとめ
・thenable is yieldables
 ・個々の処理はPromiseベースでくるんでおき
 ・Promiseで事足りるならそのまま
 ・複雑性が増しそうならgeneratorの世界を訪れる
→ 気軽に行き来出来る!
PromiseとGeneratorで気持ち良い非同期処理を!
Questions
Appendix
Promise 内部実装イメージ
	
  $	
  node	
  promise.js	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
42
Promise 内部実装イメージ
	
  $	
  node	
  promise.js	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
42
Promise 内部実装イメージ
	
  $	
  node	
  promise.js	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
42
Promise 内部実装イメージ
	
  $	
  node	
  promise.js	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
42
Promise 内部実装イメージ
	
  $	
  node	
  promise.js	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
42
Promise 内部実装イメージ
	
  $	
  node	
  promise.js	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
42
Promise 内部実装イメージ
	
  $	
  node	
  promise.js	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
42
Demo
Generator
Stream
・サイズの大きいdataを取り扱うI/O
 ・dataをchunkに分割
 ・メモリ効率
 ・パフォーマンス
  ・読み込みながら(並列的に)別処理
 ・優れたインターフェース
  ・pipeで繋ぐ
Stream

More Related Content

Node.js 実践非同期処理