$30 off During Our Annual Pro Sale. View Details »
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
おもらし Resolve
Search
Ryotaro Ko
November 01, 2019
Programming
0
710
おもらし Resolve
Retty Engineer Meetup#1 (
https://retty.connpass.com/event/152101/
) で話した LT の公開用スライドです。
Ryotaro Ko
November 01, 2019
Tweet
Share
More Decks by Ryotaro Ko
See All by Ryotaro Ko
タイ語のサジェストを日本人の俺が頑張った道のり
pikatenor
0
150
Other Decks in Programming
See All in Programming
Github Copilotのチャット履歴ビューワーを作りました~WPF、dotnet10もあるよ~ #clrh111
katsuyuzu
0
110
React Native New Architecture 移行実践報告
taminif
1
160
ViewファーストなRailsアプリ開発のたのしさ
sugiwe
0
490
エディターってAIで操作できるんだぜ
kis9a
0
730
Tinkerbellから学ぶ、Podで DHCPをリッスンする手法
tomokon
0
130
新卒エンジニアのプルリクエスト with AI駆動
fukunaga2025
0
230
tsgolintはいかにしてtypescript-goの非公開APIを呼び出しているのか
syumai
7
2.2k
Microservices rules: What good looks like
cer
PRO
0
1.5k
関数実行の裏側では何が起きているのか?
minop1205
1
700
C-Shared Buildで突破するAI Agent バックテストの壁
po3rin
0
390
251126 TestState APIってなんだっけ?Step Functionsテストどう変わる?
east_takumi
0
320
ローターアクトEクラブ アメリカンナイト:川端 柚菜 氏(Japan O.K. ローターアクトEクラブ 会長):2720 Japan O.K. ロータリーEクラブ2025年12月1日卓話
2720japanoke
0
730
Featured
See All Featured
Building an army of robots
kneath
306
46k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
9.8k
A Tale of Four Properties
chriscoyier
162
23k
Being A Developer After 40
akosma
91
590k
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
Automating Front-end Workflow
addyosmani
1371
200k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
231
22k
Reflections from 52 weeks, 52 projects
jeffersonlam
355
21k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
5.8k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
We Have a Design System, Now What?
morganepeng
54
7.9k
Transcript
+4ςετςΫχοΫ CZ3ZPUBSP,P!QJLBUFOPS ʙ͓Β͠1SPNJTFͷճʙ
͜Ε3FUUZ&OHJOFFS.FFUVQͰͨ͠-5ͷެ։༻ࢿྉͰ͢ IUUQTSFUUZDPOOQBTTDPNFWFOU
͓લ୭ͩ 3FUUZגࣜձࣾ8FCݕࡧνʔϜΤϯδχΞ 3ZPUBSP,P *%େମ!QJLBUFOPS େֶଔۀޙೖࣾ ۀྖҬ όοΫΤϯυ ݕࡧ࣭վળ &MBTUJDTFBSDIͷ͓कΓ
Πϯϑϥख͍ 0ODBMM
͜Μͳςετ "XFTPNFͳϑΥʔϜ ૹ৴ ॲཧͷྲྀΕ
͜Μͳςετ ϐΧνϡ ૹ৴ ॲཧͷྲྀΕ
͜Μͳςετ ϐΧνϡ ૹ৴ ॲཧͷྲྀΕ ೖྗྃޙɺૹ৴ϘλϯΛԡ͢ ˣ
͜Μͳςετ ϐΧνϡ ૹ৴ ॲཧͷྲྀΕ ೖྗྃޙɺૹ৴ϘλϯΛԡ͢ ˣ Ϙλϯ͕άϨʔΞτ͢Δ<BUUSEJTBCMFE> ˣ
͜Μͳςετ ϐΧνϡ ૹ৴ ॲཧͷྲྀΕ ೖྗྃޙɺૹ৴ϘλϯΛԡ͢ ˣ Ϙλϯ͕άϨʔΞτ͢Δ<BUUSEJTBCMFE> ˣ "1*௨৴ ˣ
"1*αʔόʔ
͜Μͳςετ ϐΧνϡ ૹ৴ ॲཧͷྲྀΕ ೖྗྃޙɺૹ৴ϘλϯΛԡ͢ ˣ Ϙλϯ͕άϨʔΞτ͢Δ<BUUSEJTBCMFE> ˣ "1*௨৴ ˣ
ྃͨ͠Βݩʹ͢<BUUS> "1*αʔόʔ
͜Μͳςετ ϐΧνϡ ૹ৴ ॲཧͷྲྀΕ ೖྗྃޙɺૹ৴ϘλϯΛԡ͢ ˣ Ϙλϯ͕άϨʔΞτ͢Δ<BUUSEJTBCMFE> ˣ "1*௨৴ ˣ
ྃͨ͠Βݩʹ͢<BUUS> "1*αʔόʔ ૹ৴Ϙλϯ͕ԡ͞Ε͔ͯΒ௨৴ྃ·Ͱ disabledͰ͋Δ͜ͱΛςετ͍ͨ͠
ίϯϙʔωϯτͷίʔυྫ <template> <form> <input v-model="name" placeholder="Awesome Form"/> <button type="submit" :disabled="loading">ૹ৴</button>
</form> </template> <script> import { callAPI } from 'API௨৴͢Δͭ'; export default { data() { return { name: '', loading: false, }; }, methods: { async onSubmit() { this.loading = true; try { await callAPI(this.name); this.$emit('success'); } catch (error) { // ͳΜ͔Δ } finally { this.loading = false; } }, }, }; </script>
ίϯϙʔωϯτͷίʔυྫ <template> <form> <input v-model="name" placeholder="Awesome Form"/> <button type="submit" :disabled="loading">ૹ৴</button>
</form> </template> <script> import { callAPI } from 'API௨৴͢Δͭ'; export default { data() { return { name: '', loading: false, }; }, methods: { async onSubmit() { this.loading = true; try { await callAPI(this.name); this.$emit('success'); } catch (error) { // ͳΜ͔Δ } finally { this.loading = false; } }, }, }; </script> BTZODBXBJU
Γ͍ͨςετ describe('onSubmit', () => { it('activates loading flag when form
submitted', () => { // before submit expect(wrapper.vm.loading).toBe(false); // waiting API call expect(wrapper.vm.loading).toBe(true); // after submission completed expect(wrapper.vm.loading).toBe(false); }); });
Γ͍ͨςετ describe('onSubmit', () => { it('activates loading flag when form
submitted', () => { // before submit expect(wrapper.vm.loading).toBe(false); // waiting API call expect(wrapper.vm.loading).toBe(true); // after submission completed expect(wrapper.vm.loading).toBe(false); }); }); ͜͜Ͳ͏͢Μͷ
ωλΒ͠ ͓Β͠1SPNJTF1SPNJTFͷSFTPMWFϋϯυϥͷείʔϓΛ֎ʹ࿙Β͢ 3FTPMWF
1SPNJTFSFTPMWF
Promise.resolve(value) • valueͰ3FTPMWF͞ΕͨPromiseΛฦ͢ • ͭ·Γ͜͏ function rizorubu(value) { return new
Promise(function(resolve){ resolve(value); }) } 1SPNJTFSFTPMWF
function rizorubu(value) { return new Promise(function(resolve){ resolve(value); }) }
let leakedResolve; function rizorubu(value) { return new Promise(function(resolve){ leakedResolve =
resolve; }) } 3FTPMWFͷ࿙Β͔ͨ͠
let leakedResolve; function rizorubu(value) { return new Promise(function(resolve){ leakedResolve =
resolve; }) } 3FTPMWFϋϯυϥ͕ είʔϓ֎ʹ࿙ΕΔ 3FTPMWFͷ࿙Β͔ͨ͠
let leakedResolve; function rizorubu(value) { return new Promise(function(resolve){ leakedResolve =
resolve; }) } leakedResolve(Promise.resolve("poyo")); BTZODGVODUJPOrezorubu()Λ ͖ͳͱ͖ʹ3FTPMWFͰ͖Δʂ 3FTPMWFͷ࿙Β͔ͨ͠ 3FTPMWFϋϯυϥ͕ είʔϓ֎ʹ࿙ΕΔ
Γ͍ͨςετ describe('onSubmit', () => { it('activates loading flag when form
submitted', () => { // before submit expect(wrapper.vm.loading).toBe(false); // waiting API call expect(wrapper.vm.loading).toBe(true); // after submission completed expect(wrapper.vm.loading).toBe(false); }); });
ίϯϙʔωϯτͷίʔυྫ <template> <form> <input v-model="name" placeholder="Awesome Form"/> <button type="submit" :disabled="loading">ૹ৴</button>
</form> </template> <script> import { callAPI } from 'API௨৴͢Δͭ'; export default { data() { return { name: '', loading: false, }; }, methods: { async onSubmit() { this.loading = true; try { await callAPI(this.name); this.$emit('success'); } catch (error) { // ͳΜ͔Δ } finally { this.loading = false; } }, }, }; </script>
ίϯϙʔωϯτͷίʔυྫ <template> <form> <input v-model="name" placeholder="Awesome Form"/> <button type="submit" :disabled="loading">ૹ৴</button>
</form> </template> <script> import { callAPI } from 'API௨৴͢Δͭ'; export default { data() { return { name: '', loading: false, }; }, methods: { async onSubmit() { this.loading = true; try { await callAPI(this.name); this.$emit('success'); } catch (error) { // ͳΜ͔Δ } finally { this.loading = false; } }, }, }; </script>
݁ہ͜͏ͳͬͨ let apiResolve; jest.mock('API௨৴͢Δͭ', () => ({ callAPI: () =>
new Promise(resolve => { apiResolve = resolve; }), })); describe('AwesomeForm', () => { let wrapper; beforeEach(() => { wrapper = shallowMount(AwesomeForm); }); +FTUͱWVFUFTUVUJMTΛ͍ͬͯ·͢ describe('onSubmit', () => { it('activates loading flag when form submitted', async () => { // before submit expect(wrapper.vm.loading).toBe(false); const submissionPromise = wrapper.vm.onSubmit(); // waiting API call await wrapper.vm.$nextTick(); expect(wrapper.vm.loading).toBe(true); apiResolve(Promise.resolve(true)); await submissionPromise; // after submission completed expect(wrapper.vm.loading).toBe(false); }); }); });
݁ہ͜͏ͳͬͨ let apiResolve; jest.mock('API௨৴͢Δͭ', () => ({ callAPI: () =>
new Promise(resolve => { apiResolve = resolve; }), })); describe('AwesomeForm', () => { let wrapper; beforeEach(() => { wrapper = shallowMount(AwesomeForm); }); +FTUͱWVFUFTUVUJMTΛ͍ͬͯ·͢ describe('onSubmit', () => { it('activates loading flag when form submitted', async () => { // before submit expect(wrapper.vm.loading).toBe(false); const submissionPromise = wrapper.vm.onSubmit(); // waiting API call await wrapper.vm.$nextTick(); expect(wrapper.vm.loading).toBe(true); apiResolve(Promise.resolve(true)); await submissionPromise; // after submission completed expect(wrapper.vm.loading).toBe(false); }); }); }); jest.mock Ͱ Λஔ͖͑ import { callAPI } from 'API௨৴͢Δͭ';
݁ہ͜͏ͳͬͨ let apiResolve; jest.mock('API௨৴͢Δͭ', () => ({ callAPI: () =>
new Promise(resolve => { apiResolve = resolve; }), })); describe('AwesomeForm', () => { let wrapper; beforeEach(() => { wrapper = shallowMount(AwesomeForm); }); describe('onSubmit', () => { it('activates loading flag when form submitted', async () => { // before submit expect(wrapper.vm.loading).toBe(false); const submissionPromise = wrapper.vm.onSubmit(); // waiting API call await wrapper.vm.$nextTick(); expect(wrapper.vm.loading).toBe(true); apiResolve(Promise.resolve(true)); await submissionPromise; // after submission completed expect(wrapper.vm.loading).toBe(false); }); }); }); +FTUͱWVFUFTUVUJMTΛ͍ͬͯ·͢ jest.mock Ͱ Λஔ͖͑ import { callAPI } from 'API௨৴͢Δͭ'; ͓Β͠
݁ہ͜͏ͳͬͨ let apiResolve; jest.mock('API௨৴͢Δͭ', () => ({ callAPI: () =>
new Promise(resolve => { apiResolve = resolve; }), })); describe('AwesomeForm', () => { let wrapper; beforeEach(() => { wrapper = shallowMount(AwesomeForm); }); describe('onSubmit', () => { it('activates loading flag when form submitted', async () => { // before submit expect(wrapper.vm.loading).toBe(false); const submissionPromise = wrapper.vm.onSubmit(); // waiting API call await wrapper.vm.$nextTick(); expect(wrapper.vm.loading).toBe(true); apiResolve(Promise.resolve(true)); await submissionPromise; // after submission completed expect(wrapper.vm.loading).toBe(false); }); }); }); +FTUͱWVFUFTUVUJMTΛ͍ͬͯ·͢ MPBEJOHUSVF Λݕূͯ͠3FTPMWF ΦέΦέΦοέʔ
Promise.reject(reason) • reasonʹΑΓ3FKFDU͞ΕͨPromiseΛฦ͢ • ɹɹ Έ͍ͨʹॻ͘͜ͱͰΤϥʔ࣌ͷςετͰ͖·͢ 1SPNJTFSFKFDU leakedResolve(Promise.reject(new Error("something happened")))
References: Mozilla. "Promise.reject()". MDN Web docs. 2019/3/23. https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise/reject Mozilla. "Promise.resolve()".
MDN Web docs. 2019/3/18. https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve azu. "Javascript Promise ͷຊ". Ver 1.6.5. https://azu.github.io/promises-book/