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
730
おもらし 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
インターン生でもAuth0で認証基盤刷新が出来るのか
taku271
0
190
CSC307 Lecture 06
javiergs
PRO
0
690
Vibe Coding - AI 驅動的軟體開發
mickyp100
0
180
24時間止められないシステムを守る-医療ITにおけるランサムウェア対策の実際
koukimiura
1
110
AtCoder Conference 2025
shindannin
0
1.1k
AIによるイベントストーミング図からのコード生成 / AI-powered code generation from Event Storming diagrams
nrslib
2
1.9k
AIエージェントのキホンから学ぶ「エージェンティックコーディング」実践入門
masahiro_nishimi
5
480
360° Signals in Angular: Signal Forms with SignalStore & Resources @ngLondon 01/2026
manfredsteyer
PRO
0
130
AIによる開発の民主化を支える コンテキスト管理のこれまでとこれから
mulyu
3
380
Rust 製のコードエディタ “Zed” を使ってみた
nearme_tech
PRO
0
200
AIと一緒にレガシーに向き合ってみた
nyafunta9858
0
250
AI時代の認知負荷との向き合い方
optfit
0
160
Featured
See All Featured
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
1.9k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.3k
Unsuck your backbone
ammeep
671
58k
30 Presentation Tips
portentint
PRO
1
220
Git: the NoSQL Database
bkeepers
PRO
432
66k
From π to Pie charts
rasagy
0
120
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
120
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
Writing Fast Ruby
sferik
630
62k
sira's awesome portfolio website redesign presentation
elsirapls
0
150
Building AI with AI
inesmontani
PRO
1
700
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
62
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/