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
おもらし 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
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
440
What’s Fair is FAIR: A Decentralised Future for WordPress Distribution
rmccue
0
160
Inside of Swift Export
giginet
PRO
1
530
詳細の決定を遅らせつつ実装を早くする
shimabox
1
1k
Module Harmony
petamoriken
1
110
Verilator + Rust + gRPC と Efinix の RISC-V でAIアクセラレータをAIで作ってる話 RTLを語る会(18) 2025/11/08
ryuz88
0
340
Claude Code on the Web を超える!? Codex Cloud の実践テク5選
sunagaku
0
480
オンデバイスAIとXcode
ryodeveloper
0
450
最新のDirectX12で使えるレイトレ周りの機能追加について
projectasura
0
160
業務でAIを使いたい話
hnw
0
260
乱雑なコードの整理から学ぶ設計の初歩
masuda220
PRO
26
8k
AIを駆使して新しい技術を効率的に理解する方法
nogu66
0
590
Featured
See All Featured
Done Done
chrislema
186
16k
Practical Orchestrator
shlominoach
190
11k
Java REST API Framework Comparison - PWX 2021
mraible
34
9k
Product Roadmaps are Hard
iamctodd
PRO
55
12k
Building an army of robots
kneath
306
46k
Become a Pro
speakerdeck
PRO
29
5.6k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.2k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
359
30k
Rebuilding a faster, lazier Slack
samanthasiow
84
9.3k
Mobile First: as difficult as doing things right
swwweet
225
10k
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/