Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
RxJS概要とリアクティブ アーキテクチャ
Search
dsuket
March 21, 2016
Technology
4
2.1k
RxJS概要とリアクティブ アーキテクチャ
ng-japan2016でのRxJSの話
dsuket
March 21, 2016
Tweet
Share
More Decks by dsuket
See All by dsuket
ぼくのアプリがカイゼンできない
dsuket
1
1.3k
Other Decks in Technology
See All in Technology
Amazon Location Serviceを使ってラーメンマップを作る
ryder472
2
150
第27回クラウド女子会 ~re:Invent 振り返りLT会~ 宣言型ポリシー、使ってみたらこうだった!
itkr2305
0
290
インシデントキーメトリクスによるインシデント対応の改善 / Improving Incident Response using Incident Key Metrics
nari_ex
0
4.1k
攻撃者の視点で社内リソースはどう見えるのかを ASMで実現する
hikaruegashira
4
2.1k
[JAWS-UG栃木]地方だからできたクラウドネイティブ事例大公開! / jawsug_tochigi_tachibana
biatunky
0
130
[TechNight #86] Oracle GoldenGate - 23ai 最新情報&プロジェクトからの学び
oracle4engineer
PRO
1
170
GitLab SelfManagedをCodePipelineのソースに設定する/SetGitLabSelfManagedtoCodePipeline
norihiroishiyama
1
120
業務ツールをAIエージェントとつなぐ - Composio
knishioka
0
110
Makuake*UPSIDER_LightningTalk
upsider_tech
0
200
トレードオフスライダーにおける品質について考えてみた
suzuki_tada
3
180
Amazon Aurora バージョンアップについて、改めて理解する ~バージョンアップ手法と文字コードへの影響~
smt7174
1
240
Autify Company Deck
autifyhq
2
41k
Featured
See All Featured
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
3.7k
Bootstrapping a Software Product
garrettdimon
PRO
305
110k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
330
21k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
226
22k
Building an army of robots
kneath
302
45k
Product Roadmaps are Hard
iamctodd
PRO
50
11k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
33
2.8k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
175
51k
Making Projects Easy
brettharned
116
6k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
160
15k
4 Signs Your Business is Dying
shpigford
182
22k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Transcript
RxJS֓ཁͱ ϦΞΫςΟϒ ΞʔΩςΫνϟ ng-japan 2016 OpenWeb Technology Daisuke. Takaoka With
About me ߴԬେհ ελʔτΞοϓCTOɺٕज़ސɺٕज़૬ஊͳͲ ϑϩϯτ͔ΒΠϯϑϥ·Ͱ ࠷ۙόοΫΤϯυͰRxJSͬͯ·͢ Angular2ͬͯͳͷͰ ؒҧͬͯͯ͝צห͍ͩ͘͞ŋŋŋ @dsuket
TechFeed IUUQTUFDIGFFEJP *5ςΫϊϩδʔઐͷΩϡϨʔγϣϯαʔϏε
What’s TechFeed ? ڵຯͷ͋ΔτϐοΫΛબ͢ΔͱɺຖͦͷτϐοΫ ʹؔ࿈͢ΔχϡʔεΛϋΠϥΠτͰ͓ಧ͚͠·͢ɻ
ͪΖΜɺ ʮϦΞΫςΟϒϓϩάϥϛϯάʯ τϐοΫ͋Γ·͢ʂ https://techfeed.io/channels/Reactive%20Programming
techfeed.io Register now!!
RxJS֓ཁ
What RxJS? Reactive Extensions for JavaScript • .NETͷϥΠϒϥϦͱͯ͠ੜ • ࣌ؒ࣠ͷ͋ΔඇಉظετϦʔϜ
• ؔܕϦΞΫςΟϒϓϩάϥϛϯάʢFRPʣ • Angular2Ͱ࠾༻ʂ
Functional Reactive programming The introduction to Reactive Programming you've been
missing ݴ͍͍ͨ͜ͱશ෦͜͜ʹ͋Δ ʲ༁ʳ͋ͳ͕ͨٻΊ͍ͯͨϦΞΫςΟϒϓϩάϥϛϯάೖ
ؔܕϦΞΫςΟϒϓϩάϥϛϯά (FRP) ͱ? ʮStackoverflowͷൣతղʯ Conal Elliott • ࣌ؒΛ͔͚ͯμΠφϛοΫʹมԽ͢ΔɺϑΝʔετΫϥεͷ Ͱ͢ɻͦΕΒΛؔͷ in/out
ʹͯ͠Έ߹ΘͤΔ͜ͱ͕Ͱ͖· ͢ɻ͜ΕΛ Behavior ͱݺͼ·͢ɻ • Behavior ɺ੩తͳಈ࡞࣌ܭͷΑ͏ͳ࣌ؒͱ͍͍͔ͬͨͭ͘ͷ ϓϦϛςΟϒͳͷ͔Βߏஙͨ͠ޙɺॱ൪·ͨฒྻʹଓʹ͠ ·͢ɻnݸͷ Behavior ɺ࿈ଓͨ࣌ؒ͠ͷΑ͏ͳࢄతͳ nݸͷ ؔʹΑͬͯ߹͞Ε·͢ɻ • ͦͷ ࢄతݱΛදͨ͢Ίʹ ༗ݶ·ͨແݶʹग़ݱ͢Δετ ϦʔϜΛ࣋ͭ Event ͕͋Γ·͢ɻEvent ࣌ؒͱͷϖΞͰ͢ɻ ݩMSͷResearcherͰFRPͷ࢝ͱݴΘΕΔConal Elliottͷղઆɻ Α͘ࢀর͞ΕΔ͕ɺ৽ਓ͖Ͱͳ͍
ؔܕϦΞΫςΟϒϓϩάϥϛϯά (FRP) ͱ? ʮReactive Manifestoʯ ϦΞΫςΟϒγεςϜͱ: ଈԠੑɺোੑɺྗੑɺϝοηʔδۦಈΛඋ͑Δ ϓϩδΣΫτϚωʔδϟϏδωεܥͷਓؒʹݟͤΔͷͷΑ͏ͩɻ
ؔܕϦΞΫςΟϒϓϩάϥϛϯά (FRP) ͱ? "Rx = Observables + LINQ + Schedulers”
ɾObservables: σʔλετϦʔϜ ɾLINQ(Language-Integrated Query): ΫΤϦ ɾSchedulers: ฏߦੑ੍ޚ ͱͯॏͨ͘ɺզʑΛࠞཚͤ͞ΔϚΠΫϩιϑτతͳͷͩɻ
ؔܕϦΞΫςΟϒϓϩάϥϛϯά (FRP) ͱ? ඇಉظσʔλετϦʔϜΛ༻͍Δϓϩάϥϛϯά • ετϦʔϜͱ࣌ؒॱʹฒΜͩਐߦதͷΠϕϯτͷྻ • ετϦʔϜͷΠϕϯτΛඇಉظʹॲཧ • ετϦʔϜΛ߹ɺ࡞ɺϑΟϧλ͢Δศརͳؔ܈
• ܰྔͰԿͰετϦʔϜʹͰ͖Δ
ϘλϯΫϦοΫͷΠϕϯτετϦʔϜ ΫϦοΫΠϕϯτ ετϦʔϜͷྃ Τϥʔ ࣌ؒॱʹฒΜͩΠϕϯτྻΛඇಉظʹॲཧ͢Δ ετϦʔϜ ʹ Observable (*1) *1
ʢࢲ͜ΕΛഅ໊ࣛ͛ͨલͩͱײ͡ΔͷͰɺετϦʔϜͱݺͿɻ@andrestaltzʣ
μϒϧ ΫϦοΫ ͷྫ
Push vs Pull ObservableϒϩοΫͤͣʹෳͷΛ ϦΞΫςΟϒʹॲཧͰ͖ΔɻPromise++ What are the Reactive Extensions
for JavaScript (RxJS)? ୯ҰͷΓ ෳͷΓ 1VMMಉظతରܕ 0CKFDU "SSBZ 4FU .BQ 0CKFDU 1VTIඇಉظ3FBDUJWF 1SPNJTF 0CTFSWBCMF
Passive vs Reactive BarFoo͔Βૢ࡞͞Εɺ ঢ়ଶ͕֎෦ʹґଘ͢Δɻ BarFooͷΠϕϯτΛड͚ ࣗͰঢ়ଶΛཧ͢Δɻ ReactiveϓϩάϥϛϯάͰࣗʹΛͭϞδϡʔϧΛͭ͘Γɺ֎෦ ͷঢ়ଶΛมߋ͢Δ͜ͱΑΓϞδϡʔϧࣗͷػೳʹযΛ߹ΘͤΔɻ ؔ৺ͷʹܨ͕Δ
Observables › Cycle.js How Reactive Programming can help reduce code spaghetti Passive/Reactive ϓϩάϥϛϯάͷҧ͍ΛֶͿ
ͳͥReactiveProgramming͕ඞཁ͔ʁ ”” ݱͷΞϓϦɺߴʹΠϯλϥΫςΟϒͳମݧϢʔβʔʹ༩͑ ΔͨΊʹɺଟͷϦΞϧλΠϜΠϕϯτΛѻ͍ͬͯΔɻզʑ͜ ΕΛదʹऔΓѻ͏πʔϧΛ୳͓ͯ͠ΓɺϦΞΫςΟϒϓϩάϥ ϛϯά͕ͦͷ͑ͳͷͩɻ @andrestaltz
ͳͥReactiveProgramming͕ඞཁ͔ʁ ”” ϢʔβʔϦΞϧλΠϜΛظ͍ͯ͠ΔɻੈքpushʹҠಈ͠ ͨɻϢʔβʔզʑ։ൃऀ͕͍ͭ͘ͷΛ͍ͬͯΔɻ Intro to Rx - Why Rx?
Rx ʹ͍͍ͯΔͷɺ͍ͳ͍ͷ RxΛ͏͖ͷ • ϚεϘλϯΫϦοΫͷΑ͏ͳUIΠϕϯτɺΞϓϦέʔγϣϯͷΠϕϯτɺΠϯϑ ϥγεςϜͷΠϕϯτɺωοτϫʔΫΠϕϯτɺCEPͳͲͷඇಉظΠϕϯτॲཧશൠ Rx͕͑Δͷ • λεΫɺඇಉظγεςϜίʔϧͳͲ୯Ұͷඇಉظॲཧ ͔ͳ͍ͷ
• طଘͷಉظॲཧΛஔ͖͑Δ͚ͩͷͷ • ϝοηʔδΩϡʔͳͲɺγʔέϯγϟϧͳτϥϯβΫγϣϯ͕ඞཁͳͷ intro to Rx - When is Rx appropriate?
ECMAScript Observable • Observable ͕ ES7ʹఏҊ͞Ε͍ͯͯೖΓͦ͏ https://github.com/zenparsing/es-observable ೦ͷͨΊɺAngular1Ϣʔβʔʹࢥ͍ೖΕਂ͍ Object.observe ͱผw
ࠓͪΌΜͱೖΓͦ͏ʁ • RxJS(v5) ES7 Observable ४ڌ
Rxͷؒୡ Languages • RxJava, RxJS, Rx.NET, RxScala, RxGroovy, RxJRuby, •
UniRx, RxCpp, RxClojure, Rx.rb RxPY, RxKotlin, RxSwift Platforms and frameworks • RxNetty, RxAndroid, RxCocoa http://reactivex.io/languages.html
Other FRP libraries • Bacon.js • RxJSͷޙൃ FRPϥΠϒϥϦɻRxJSΑΓҰ؏ੑ͋Γɺ ͍͍͕͢ύϑΥʔϚϯεʹগ͋͠Γʁ •
Kefir • Bacon.jsͷ͞ΒʹޙൃɻলαΠζɺলϝϞϦɻ ͲͪΒES7 ObservableͱҟͳΓͦ͏ͳͨΊɺࠓޙ͕ඍົ
RxJSجૅ
RxJSͷҙ • ݱࡏ RxJS 4ܥͱ5ܥ͕͋ΓɺϦϙδτϦ͕ҧ͏ • 4ܥ: Reactive-Extensions/RxJS •
5ܥ: ReactiveX/RxJS ʢ·ͩbeta2ɻAngular2Ͱ࠾༻ʣ • v5ͰAPI͕౷ഇ߹͞Εͯ݁ߏมΘͬͯΔʂ • ᷿ͷυΩϡϝϯτ΄ͱΜͲ͕4ܥɻ֓೦େ͖͘มΘͬͯͳ͍͕ɻɻ • Migrating from RxJS 4 to 5 ඞಡ • ·ͩυΩϡϝϯτ͞Εͳ͍ଟ͍ͷͰιʔεಡΉඞཁ • ຊࢿྉ v5 ରԠͰઆ໌͠·͢
RxJSͷجຊ RxJS = Observables + Operators + Schedulers • Observable:
σʔλετϦʔϜ Rx.Observable.of / from / create ͳͲͰࣗ༝ʹ࡞ΕΔɻ • Operators: ΫΤϦ mapͱ͔filterͱ͔ɺObservableΛૢ࡞͢Δؔ • Schedulers: ฒߦੑͷίϯτϩʔϧ
جຊతͳॲཧ • ݩͷsource͔ΒObservableΛ࡞͠ɺΦϖϨʔλͰૢ ࡞͠ɺͦͷ݁ՌΛड͚ͯॲཧ͢Δɻ • ετϦʔϜ͔ΒσʔλΛड͚औΔ͜ͱΛSubscribeͱ͍ ͏ɻ • v5 Ͱ
ES7 ObservableͷΠϯλʔϑΣΠεʹ߹Θͤͨ • ʢجຊతʹʣSubscribe͢Δͱσʔλ͕ྲྀΕ࢝ΊΔɻ
؆୯ͳαϯϓϧ const stream = Rx.Observable.range(0,5) // 0,1,2,3,4 .map(x => x
* 3) // => 0,3,6,9,12 .filter(x => x%2); // => 3,9 stream.subscribe({ next: x => console.log(‘Next:' + x), error: err => console.error('Error:', err), complete: () => console.log('Completed'), }); => "Next:3" => "Next:9" => "Completed"
API֓ཁ • ͱʹ͔͘ΦϖϨʔλͷ͕ଟ͍ɻ • v4ܥͰ144ݸɺv5.0.0.beta.2Ͱ98ݸ • ੜɺมɺϑΟϧλϦϯάɺ݁߹ͳͲ • Ҏ߱Α͘͏ϐοΫΞοϓ
ࢀߟ: reactivex.io • RxͷΦϖϨʔλΛݴޠຖʹղઆ • ਤ͕ղɻ׳ΕΕಡΊΔ
ࢀߟ: RxMarbles • ΦϖϨʔλΛΠϯλϥΫςΟϒʹਤղ
ࢀߟ: ͦͷଞΑ͘ಡΉࢿྉ • RxJS/observable.md at master · Reactive-Extensions/RxJS • v4ͷAPIυΩϡϝϯτ
• RxJS/MIGRATION.md at master · ReactiveX/RxJS • v4͔Β5ͷϚΠάϨʔγϣϯΨΠυ • RxJS/src/operator at master · ReactiveX/RxJS • v5 ͷΦϖϨʔλҰཡʢsrcʣ • RxJS Advent Calendar 2015 • @bouzuya ͞ΜͷᕒͷಠΓΞυΧϨ
ੜ • Rx.Observable.of • ୯ҰͷΛͱΓɺͦΕΛฦ͢ετϦʔϜΛੜ • just/return ofʹٵऩ͞Εͨ • Rx.Observable.from
• ྻɺPromiseɺObservableͳͲΛऔΓɺͦΕΒෳͷͷετ ϦʔϜΛੜ • Rx.Observable.range / repeat • ࢦఆൣғɺ·ͨͷ࿈ଓͨ͠ετϦʔϜΛੜ • Rx.Observable.interval / timer • ҰఆִؒͰ܁Γฦ͢ • Rx.Observable.create • subscriberΛҾʹҙͷΛྲྀ͢ετϦʔϜΛੜ
ม • map (select) • Λม͢Δ • select v5
ͰഇࢭɻΛऔΔ߹ɺmapTo ʹɻ • mergeMap (flatMap) • map ݁Ռ͕Observableྻͷ߹Α͘͏ • v5 Ͱ mergeMap ʹɻObservableΛऔΔ߹ɺmergeMapTo ʹɻ • scan • reduceͬΆ͍͕ɺΛྲྀ͢ • groupBy • άϧʔϓ͚ʢׂʣ͢Δ • buffer / bufferCount / bufferTime • ࣌ؒͰΠϕϯτ·ͱΊΔ
ϑΟϧλϦϯά • filter (where) • ͳͲͰϑΟϧλϦϯά͢Δ • where v5
Ͱഇࢭɻ • first / last • ࠷ॳ࠷ޙͷ͚ͩΛऔΔ • skip / skipLast • ࢦఆͷnݸΛඈ͢ɻskipLast v5Ͱഇࢭ • take / takeLast • ࢦఆͷnݸΛऔಘ͢ΔɻtakeLast࠷ޙͷnݸɻ • distinct • ϢχʔΫʹͯ͠औಘ͢Δɻ • sample / debounce • ࢦఆִؒຖͷ࠷ޙͷΛऔಘ͢Δɻ
݁߹ • startWith • ॳظΛ࠷ॳʹૠೖ • merge • ετϦʔϜΛ݁߹͢ΔɻෳͰOK •
switch • ετϦʔϜΛॱʹྲྀ͢ • combineLatest • ෳͷετϦʔϜͷ࠷ޙͷΛ݁߹͢Δɻ • Ͳ͔͜1ͭͰདྷΕɺଞͷετϦʔϜͷۙͷͱ݁߹͢Δ • zip • ෳͷετϦʔϜͷ࠷ޙͷΛ݁߹͢Δɻ • શ෦ἧ͔ͬͯΒग़ྗ͞ΕΔɻ • and / then / when • v5Ͱഇࢭʁ
࣮ફRxJS
ζϯυίΩϤγ
·ͩ·ͩଓ͘ŋŋŋ
࡞ͬͯΈͨ https://jsbin.com/kecove/edit?js,console
ղઆ1: randomStream const randomStream = Rx.Observable .create(observer => { observer.next(!Math.floor(Math.random()*2));
observer.complete(); }); Everything is a stream Observable.create ͰɺϥϯμϜʹtrue/falseΛฦ͢ ετϦʔϜΛ࡞
ղઆ2: zundokoStream const zun = Rx.Observable.of('ズン'); const doko = Rx.Observable.of('ドコ');
return randomStream .flatMap(val => (val ? zun : doko)); “ζϯ” ͱ ”υί” Λฦ͢ετϦʔϜΛ࡞͠ɺ randomStreamͷʹΑͬͯΓସ͑Δɻ
ղઆ3: intervalStream return Rx.Observable.interval(400) .mergeMapTo(zundoko) .do(val => console.log(val)) .bufferCount(5, 1)
.takeWhile(val => val.join('') !== 'ズンズンズンズンドコ'); Observable.interval Ͱ 400msຖʹ܁Γฦ͢ετϦʔϜΛ࡞͠ ͦΕΛmargeMapToͰzundokoStreamʹஔ͖͑Δɻ doͰ్த݁ՌΛग़ྗͭͭ͠ɺbufferCount ͰskipΛ1Ͱ5ݸηο τɻtakeWhile ͰతͷจࣈྻʹͳΔ·Ͱ܁Γฦ͢ɻ
ղઆ4: subscribe const source = createStream(); source.subscribe({ next: () =>
{}, error: err => console.log('Error: ', err), complete: () => console.log('キ・ヨ・シ!'), }); ࡞ͨ͠StreamΛsubscribeͯ͠ɺྃ࣌ʹจࣈ ྻΛग़ྗ͢Δɻ
༨ஊ ಉ͜͡ͱ͕͜Ε1ߦ(87byte)ͰࡁΈ·͢ʢྦ ʢ͖ͬ͞ͷ764byteʣ for(n=3;n-64;console.log(n-64?(n|=2*Math.random())&1?' ドコ':'ズン':'キ・ヨ・シ!'))n<<=6 jsͰζϯυίΩϤγͷίʔυΰϧϑ
RxJS·ͱΊ • ࠓ͔ΒReactive ProgrammingΔͳΒRxJS 5ʂ • ΦϖϨʔλ͕ࢁ΄Ͳ͍͋ͬͯ͜ͳ͢ͷ ͍͠ɻ • ·͍ͣ͜͠ͱߟ͑ͣʹɺجຊతͳΦϖϨʔ
λͰ࡞ͬͯΈΔɻ ʢͦ͏͠ͳ͍ͱ͍ͭ·Ͱ͠ͳ͍ɾɾɾʣ
Reactive Architecture RxJS + 2
RxJS in Angular2 • Angular2ͰҰ෦ͰRxJSΛ࠾༻ • HTTP • EventEmitter •
ίϯϙʔωϯτΠϕϯτHTTPϦΫΤετΛ Observableͱͯ͠ѻ͑Δʂ • ViewͰObservableΛදࣔՄೳ
Angular2 Architecture Angular2Componentࢦ RxJSͬͯσʔλϑϩʔΛߟ͑ΒΕͳ͍͔
Reactive Architecture UNIDIRECTIONAL USER INTERFACE ARCHITECTURES ϢʔβʔΠϕϯτΛ୯Ұํͷσʔλϑϩʔͱ ͯ͠ѻ͏ΞʔΩςΫνϟͷҰཡΛհ FluxɺReduxɺBESTɺModel-View-Updateɺ Model-View-IntentɺNested
Dialogues
Flux • Store, View, Action, Dispatcher ͔ΒΔ • ViewReactComponentͷೖΕࢠʹͳΔ •
ViewͰϨϯμϦϯάͱΠϕϯτϋϯυϦϯάΛߦ͏
Redux • Singleton Store, Provider, Actions, Reducers • View ProviderReactҎ֎ʹAngularɺEmberͳͲͰՄ
• View͔ΒAction͕ݺΕɺActionຖʹReducerͰstateΛߋ৽͢Δ
Model-View-Update • “The Elm Architecture” ͱͯ͠ΒΕΔɻRedux͜Εʹinspire͞Εͨɻ • Model, View, Action,
UpdateΛComponentͱͯ͠֊ߏԽͰ͖Δɻ
Model-View-Intent • Cycle.js Ͱ࠾༻͞Ε ObservableΠϕϯτετϦʔϜΛσʔλϑϩʔͱ͢Δ • UserΠϕϯτϋϯυϥIntentͰએݴ͞ΕɺϨϯμϦϯάͱ • MVIComponentʹͳΓɺ֊తʹ͑Δ
Angular2ͰͷReactive Architectureͷݕ౼ • Angular2ͷComponentར༻͍ͨ͠ɻ֊Խͱؚ͔Ίɻ • MVIͷObservableத৺ͷߟ͑Αͦ͞͏ɻ • ComponentʹModelɼIntent૬ΛObservableͰೖΕͯΈΔɻ • ϞσϧΛObservableʹ͠ɺViewͰͦΕΛ͏
• ΠϕϯτϋϯυϦϯάAngularͷόΠϯσΟϯά͕ศརͳͷͰͦΕ Λ͏ɻ • όΠϯσΟϯάΛView͔Βग़͢͜ͱ͕ඞͣ͠ਖ਼ղͰͳ͍ͷͰɻʢؔ৺ͱٕज़ͷ ʣ
$PNQPOFOU Angular2 MVI 6TFS .PVTF *OUFOU 0CTFSWBCMF .PEFM Πϯελϯεม
0CTFSWBCMF 7JFX UFNQMBUF 4DSFFO formCtrl͔ΒϢʔβʔҙਤ ΛΠϯςϯτͱͯ͠Observableʹ Πϯςϯτ͔ΒΛऔΓग़͢ ObservableͳΠϯελϯεม ObservableมΛ asyncͰviewʹόΠϯυ
Angular2 MVI Sample ຯͳαϯϓϧ࡞ͬͯΈͨɻ • https://github.com/dsuket/angular2-mvi
@Component({ selector: 'bmi', styles: [require('./bmi.component.scss')], template:` <div class="bmi-calc"> <div class="weight">
<div class="label">Weight: </div> <input id="#weight" type=“range" [ngFormControl]="weightCtrl"> {{weight$ | async}} kg </div> <div class="height"> <div class="label">Height: </div> <input id="#height" type=“range" [ngFormControl]="heightCtrl"> {{height$ | async}} cm </div> <h3>BMI is {{bmi$ | async}}</h3> </div> `, directives: [FORM_DIRECTIVES], }) bmi.component.ts
export class BmiComponent { // Models private weight$; private height$;
private bmi$; // Controls private weightCtrl = new Control(); private heightCtrl = new Control(); constructor() { // Intents const weightChanges = this.weightCtrl.valueChanges; const heightChanges = this.heightCtrl.valueChanges; // Bind intents to models this.weight$ = weightChanges.map(Number).startWith(60); this.height$ = heightChanges.map(Number).startWith(170); this.bmi$ = this.weight$.combineLatest(this.height$) .map(this.calcBmi); } calcBmi(data) { const [weight, height] = data; const heightMeters = height * 0.01; return Math.round(weight / (heightMeters * heightMeters)); } } bmi.component.ts
ߟ Pros • ͳ͔ͳ͔ΩϨΠʹॻ͚ͦ͏ɻ • @Input ͳͲͰObservableΛΓͱΓͯ͠ɺComponentؒ࿈ܞ؆୯ ʹͰ͖ͦ͏ɻ Cons •
ຖճ async ॻ͘ͷ͕ͪΐͬͱ໘͍͘͞ɻ • ͦͦ͜ͷॻ͖ํ͕ͤͳͷ͔Ͳ͏͔Α͔͘Βͳ͍ɻɻ • ύϑΥʔϚϯεతʹͲ͏͔ؾʹͳΔɻ • ngFor ͕ Observable Λͦͷ··ѻ͑ͳ͍ͷ͕೦
༨ஊ ͖ͬ͞ͷ zundoko Λ Angular2 + MVI Ͱ࡞ͬͨ • dsuket/zundoko-angular
• Demo લηογϣϯͰ @shumpei ͕࡞ͬͨελʔλʔΩοτ͙͑͢Ͱ͖ͨɻ ͚Ͳɺશ෦ObservableͰ࡞ΔͷπϥΠŋŋŋ ࣌ؒͷ߹Ͱ݁ہී௨ͷόΠϯσΟϯάʹͳͬͨͱ͜Ζ
ࢀߟ • Cycle.js • Reactive Data Flow in Angular 2
• How to build Angular 2 apps using Observable Data Services - Pitfalls to avoid • Taking advantage of Observables in Angular 2 • todomvc-ng2-reactive • angular2-reactive-starter
·ͱΊ • ObservableES7Ͱ࠾༻͞Εͦ͏ͳͷͰɺࠓ ͔Β͓ͬͯ͜͏ʂ • ObservableΛத৺ͱͨ͠σʔλϑϩʔΞʔΩς ΫνϟࠓྲྀߦΔʂʁ • TechFeedͰτϨϯυΛ͍͔͚Α͏ʂ