ํ ์คํธ ๋๋ผ์ด๋ธ ํ๋ก์ ํธ์์ ์ค์ ๊ตฌํํด์ผ ํ๋ ๋ช ์ธ ์ค Generator ์ ์ฉ ํจ์จ์ด ์ ์ผ ๋์๋ ๋ช ์ธ๋ฅผ ์กฐ๊ธ ์์ ํ๋ค. ํ์ผ ๋๋ ํด๋๋ฅผ ์ ํํ ํ ๋ค๋ฅธ ํด๋๋ก ์ด๋ํ ๋์ ๋ช ์ธ๋ค.
๋ค์์ ์น ๊ธฐ๋ฐ ํ์ผ ์์คํ
๊ตฌํ ํ๋ก์ ํธ์ ์ผ๋ถ ๊ธฐ๋ฅ์ด๋ค.
ํ์ผ ๋ชฉ๋ก์์ ์ ํํ ๋ค์์ ํ์ผ ๋ฐ ํด๋๋ฅผ ๋ค๋ฅธ ํด๋๋ก ์ด๋ํ ์ ์๋ค.
์ด๋, ์ด๋ ๋์ ํด๋์ ์ด๋ฆ์ด ๊ฐ์ ํ์ผ ๋ฐ ํด๋๊ฐ ์ด๋ฏธ ์กด์ฌํ ๊ฒฝ์ฐ ๋ชจ๋ ๊ฑด์ ๋ํด์ ์ฌ์ฉ์์๊ฒ ํ์ธํ๋ค.
์๋ฅผ ๋ค์ด โ์ ํด๋โ๋ผ๋ ์ด๋ฆ์ด ์ค๋ณต๋ ๊ฒฝ์ฐ, โ์ด๋ํ๋ ค๋ ํด๋์ ์ด๋ฆ์ด ์ค๋ณต๋ ํด๋๊ฐ ์์ต๋๋ค.
[์ ํด๋(1)]์ด๋ผ๋ ์ด๋ฆ์ผ๋ก ๋ณ๊ฒฝ ํ ์ด๋ํ์๊ฒ ์ต๋๊น?โ๋ผ๋ ๋ฌธ๊ตฌ์ ํ์ธ์ฉ ๋์์ธ ๋ ์ด์ด๋ฅผ ๋์ด๋ค.
'ํ์ธ'์ ๋๋ฅด๋ฉด ๊ทธ ์ด๋ฆ์ผ๋ก ์ด๋์ํจ๋ค. ์ด๋ '์ดํ์ ๋ชจ๋ ํญ๋ชฉ์ ์ ์ฉ'
์ฒดํฌ๋ฐ์ค๋ฅผ ๋๋ฅด๋ฉด ์ดํ ์ค๋ณต ๊ฑด์ ๋ชจ๋ 'ํ์ธ' ์ฒ๋ฆฌํ๋ค.
'์ทจ์'๋ฅผ ๋๋ฅด๋ฉด ๊ทธ ํ์ผ์ ๋ํด ์ทจ์ํ๋ค. ๋ง์ฐฌ๊ฐ์ง๋ก '์ดํ์ ๋ชจ๋ ํญ๋ชฉ์ ์ ์ฉ'
์ฒดํฌ๋ฐ์ค๋ฅผ ๋๋ฅด๋ฉด ์ดํ ์ค๋ณต ๊ฑด์ ๋ชจ๋ '์ทจ์' ์ฒ๋ฆฌํ๋ค.
์ฌ์ฉ์๊ฐ ๋ชจ๋ ์ค๋ณต ๊ฑด์ ๋ํด ํ์ธํ๋ฉด ๋ชจ๋ ๊ฑด์ ๋ํด ์ด๋ ์ฒ๋ฆฌํ๋ค.
์๋ฒ์์ ์ ๊ณตํ๋ API ๋ชฉ๋ก
GET '/api/check-duplication'
[์ด๋ฆ ์ค๋ณต ํ์ธ]
- ํน์ ํด๋์ id์ ์์ฑํ ์ด๋ฆ์ ์ ๋ฌ
- ์ค๋ณต๋๋ ๊ฒฝ์ฐ ์ฌ์ฉ ๊ฐ๋ฅํ ์ ์ด๋ฆ๊ณผ ํจ๊ป 409 ์๋ต
- ๊ฐ๋ฅํ ๊ฒฝ์ฐ 200 ์๋ต
POST '/api/move'
[ํ์ผ ๋ฐ ํด๋ ์ด๋]
- ์ด๋ ๋์ ํ์ผ ๋ฐ ํด๋์ id ๋ชฉ๋ก๊ณผ ์ด๋ ๋์ ํด๋์ id ์ ๋ฌ
- ์ค๋ฅ๊ฐ ์์ผ๋ฉด ๋ชจ๋ ์ด๋์ ์ฒ๋ฆฌ ํ 200 ์๋ต
ํ์ผ ๋ฐ ํด๋ ์ด๋ API์์ ์ค๋ณต์ ํจ๊ป ์ฒ๋ฆฌํ๋ ๊ฒ์ด ์ด์์ ์ด์ง๋ง, ์ด ๊ธ์์ ์ค์ํ ๋ถ๋ถ์ ์๋๋ฏ๋ก ๋น์ฅ์ ๋ ๊ฐ์ API๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค๊ณ ๊ฐ์ ํ๋ค.
๋ ์ค์ API๋ ์ด๋์ ๊ฒฐ๊ณผ๋ฅผ ์น ์์ผ์ ํตํด ํด๋ผ์ด์ธํธ์๊ฒ ์๋ฆฌ์ง๋ง. ์ค๋ช ์ ์ฝ๊ฒ ํ๋ ค๊ณ ๋จ์ผ HTTP ์์ฒญ, ์๋ต์ ์ด์ฉํ๋ ๊ฒ์ผ๋ก ๊ฐ์ ํ๋ค.
๋จผ์ ํ์ฌ ์ ํ๋ ํ์ผ๊ณผ ํด๋(์ดํ '๊ฐ์ฒด' ๋ผ ํจ)์ ์ด๋ฆ๊ณผ ์ด๋ ๋์ ํด๋์ id๋ฅผ ์กฐํํด [์ด๋ฆ ์ค๋ณต ํ์ธ] API๋ฅผ ํธ์ถํด์ผ ํ๋ค. 200 ์๋ต์ ๋ฐ์ผ๋ฉด ๋ฐ๋ก [ํ์ผ ๋ฐ ํด๋ ์ด๋] API๋ฅผ ํธ์ถํ๋ฉด ๋์ง๋ง ์ค๋ณต ์ค๋ฅ๊ฐ ์๋ตํ ๊ฒฝ์ฐ ๋ชจ๋ ์ค๋ณต์ ๋ํด ์ฌ์ฉ์ ์๋ต์ ์์งํด์ผ ํ๋ค.
๋ชจ๋ ์ด๋ฆ ์ค๋ณต ๊ฑด์ ๋ํด ์ฌ์ฉ์์ ์๋ต์ ์์งํ ๋ window.confirm
์ ์ฌ์ฉํ๋ฉด ํ๋ก์ธ์ค๊ฐ ๋ฉ์ถ๊ธฐ ๋๋ฌธ์ ๋ชจ๋ ํญ๋ชฉ์ ๋ํด ์์ํ๊ฒ ์ฌ์ฉ์์ ์ ํ์ ์์งํ ์ ์๋ค.
ํ์ง๋ง '์ดํ ๋ชจ๋ ํญ๋ชฉ์ ์ ์ฉ'์ด๋ผ๋ ์ฒดํฌ๋ฐ์ค ๊ธฐ๋ฅ์ ์ง์ํด์ผ ํ๋ฏ๋ก ์ฌ์ฉํ ์ ์๋ค. ๊ฒฐ๊ตญ, ๋ณ๋์ '๋์์ธ ๋ ์ด์ด'๋ฅผ ๊ตฌํํด์ผ ํ๋ค. ์ด '๋์์ธ ๋ ์ด์ด'์์ ์ฌ์ฉ์๊ฐ ์๋ตํ๊ธฐ๊น์ง ๊ธฐ๋ค๋ฆฌ๋ ํ์๋ ์ผ์ข ์ ๋น๋๊ธฐ ์ฒ๋ฆฌ์ด๋ฏ๋ก ๊ตฌํํ๊ธฐ ๊น๋ค๋ก์ด ๋ถ๋ถ์ ์ํ๋ค.
์ ๋ฆฌํ๋ฉด '์ด๋ฆ ์ค๋ณต ํ์ธ', '์ค๋ณต๋๋ ๋ชจ๋ ํญ๋ชฉ์ ์ฌ์ฉ์ ์๋ต ์์ง', '๊ฐ์ฒด ์ด๋'์ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์์ฐจ์ ์ผ๋ก ์ํํด์ผ ํ๋ค.
์๊ตฌ์ฌํญ์ '๋์์ธ ๋ ์ด์ด'๋ฅผ ์ฝ๋ฐฑ ํจํด์ผ๋ก ๊ตฌํํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค. jsConfirm
์ ์๋ ๋ฉ์์ง๋ฅผ ๋ฐ์์ ๋ณด์ฌ์ฃผ์ด์ผ ํ์ง๋ง. ์ค์ํ ๊ฒ์ด ์๋๋ฏ๋ก ์ฒ๋ฆฌํ๋ค๊ณ ๊ฐ์ ํ์.
<div id="layer">
<input type="checkbox" id="checkbox" />
<button type="button" id="ok">ok</button>
<button type="button" id="cancel">cancel</button>
</div>
<script>
const layer = $("#layer");
const checkbox = $("#checkbox");
/**
* @param {string} msg - confirm ์ ์ถ๋ ฅํ ๋ฉ์์ง ๋ด์ฉ
* @param {function} cb - callback ํจ์
*/
function jsConfirm(msg, cb = () => {}) {
checkbox.prop("checked", false);
layer.show().on("click", ev => {
const target = $(ev.target);
const checked = checkbox.prop("checked");
if (target.is("#ok")) {
layer.hide().off();
cb({ confirmed: true, checked });
} else if (target.is("#cancel")) {
layer.hide().off();
cb({ confirmed: false, checked });
}
});
}
</script>
๊ทธ๋ค์์ ์ค๋ณต ๊ฑด์ ๋ํด ๋ฐ๋ณต์ ์ผ๋ก ์ฌ์ฉ์์ ํ์ธ์ ์์์ผ ํ๋ค. ๋จผ์ ์ด๋ฆ ์ค๋ณต ๋ฐ์ดํฐ์ Mock์ ์ค๋นํ๋ค. ์ด ๊ฐ์ฒด๋ [์ค๋ณต ํ์ธ] API์ ์๋ต์ด๋ผ๊ณ ๊ฐ์ ํ ๊ฐ์ฒด์ด๋ค.
// [์ด๋ฆ ์ค๋ณต ํ์ธ] API์ ์๋ต ๋ฐ์ดํฐ (์์ฒญํ ์ด๋ฆ, ์ฌ์ฉ๊ฐ๋ฅํ ์ด๋ฆ ์)
const dupList = [["foo", "foo(2)"], ["bar", "bar(2)"], ["baz", "baz(2)"]];
๋จ์ํ ์ฌ์ฉ์์ ์๋ต์ ์๊ธฐ ์ํด์๋ ์ฝ๋ฐฑ์ ์ฌ๊ท์ ์ผ๋ก ๊ตฌ์ฑํ๋ฉด ๋๋ค. ํ์ง๋ง ์ฝ๋ฐฑ์ ์ค์ฒฉ์ ์ง์ ์์ฑํ๋ ๊ฒ์ ํ๋ ์ฝ๋ฉ์ด๊ธฐ ๋๋ฌธ์ ๋์ ์ธ ์ค๋ณต ํญ๋ชฉ ๋ฆฌ์คํธ์ ๋์ํ ์ ์๋ค. ๋ฐ๋ผ์ ์ฌ๊ท๋ฅผ ์ฌ์ฉํ๋ค.
// ์ด ๋ณ์์ ํ์ธ ํญ๋ชฉ์ ๋ชจ์๋ค
let resolved = [];
function resolveDuplicates(idx) {
const item = dupList[idx];
jsConfirm(`msg${idx}`, ({ confirmed, checked }) => {
if (confirmed) {
// A 'ํ์ธ'
resolved.push(item);
}
idx += 1;
if (checked) {
if (confirmed) {
// B '์ดํ ๋ชจ๋ ํญ๋ชฉ์ ์ ์ฉ', 'ํ์ธ'
resolved = [...resolved, ...dupList.slice(idx)];
} else {
// C '์ดํ ๋ชจ๋ ํญ๋ชฉ์ ์ ์ฉ', '์ทจ์'
}
return;
}
if (!dupList[idx]) {
// D ๋ชจ๋ ํญ๋ชฉ ์๋ฃ
return;
}
resolveDuplicates(idx);
});
}
resolveDuplicates(0);
์์ง API ํธ์ถ ์ฒ๋ฆฌ๋ ์์์กฐ์ฐจ ํ์ง ์์๋ค. [์ค๋ณต ํ์ธ] API๋ฅผ ๋จผ์ ํธ์ถํ ํ์ ๊ฒฐ๊ณผ์ ๋ฐ๋ผ resolveDuplicates
๋ฅผ ์คํํด์ผ ํ๋ฏ๋ก ์์ ์ฝ๋๋ ์ด๋ฏธ depth๊ฐ ์ฆ๊ฐํ ์ํ์ผ ๊ฒ์ด๋ค.
๋ ์ฝ๋์ A, B, C, D ๋ถ๋ถ์์๋ API ํธ์ถ์ ์ํ ์ฝ๋ฐฑ์ด ์ถ๊ฐ๋ ๊ฒ์ด๋ค. ํจ์๋ฅผ ์ถ์ถํ๋ ๋ฐฉ๋ฒ ๋ฑ์ ๋ฆฌํฉํ ๋ง์ ํ๋ค๊ณ ํด๋ ์ฝ๋ฐฑ ํจํด์ผ๋ก๋ ํ๊ณ๊ฐ ์๋ค. ๋ง๋ค์ด์ง๋ ์ฝ๋๋ ์์๋ณด๊ธฐ ์ด๋ ต๊ณ ์ ์ง ๋ณด์ํ๊ธฐ ์ด๋ ต๋ค.
์ฝ๋ฐฑ ์ค์ฒฉ ๋ฌธ์ ๋ ์ค๋์ ๋ถํฐ ๋ฑ์ฅํ Promise๋ฅผ ์ด์ฉํ๋ฉด ์ด๋ ์ ๋ ํด๊ฒฐํ ์ ์๋ค. Promise๋ ๋ฏธ๋์ ์ด๋ค ๊ฐ์ ๋ฐ์ ์ ์๋ ๊ฐ์ฒด์ด๋ค. Kyle Simpson์ ํ๋ฒ๊ฑฐ๋ฅผ ์ฃผ๋ฌธํ๊ณ ๋ฐ๋ ๋๊ธฐํ๋ก ๋น์ ํ๋๋ฐ ์๊ธฐ์ง๋ง ์ ํํ ๋น์ ๋ค. Promise๋ ์ด๋ค ๊ฐ ํ๋๋ฅผ ๋ฐ์ ์ ์๋ ๊ฒ์ ๋ณด์ฅํ๋ ์ธํฐํ์ด์ค์ด๋ค.
'๋์์ธ ๋ ์ด์ด'์ ํ์ธ, ์ทจ์๋ ์ด Promise๋ฅผ ์ฌ์ฉํ ์ ์๋ค. '๋์์ธ ๋ ์ด์ด'๊ฐ Promise๋ฅผ ๋ฐํํ๋๋ก ๊ตฌํํด ๋ณด์. ์ด ๊ณผ์ ์ ์ด ๊ธ์ ๋์ Generator๋ฅผ ์ฌ์ฉํ ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ ์ํ ๋ฐ๊ฑฐ๋ฆ์ด๊ธฐ๋ ํ๋ค.
/**
* @param {string} msg - confirm ์ ์ถ๋ ฅํ ๋ฉ์์ง ๋ด์ฉ
* @returns {Promise}
*/
function jsConfirm(msg) {
// Return Promise
return new Promise((resolve, reject) => {
checkbox.prop("checked", false);
layer.show().on("click", ev => {
const target = $(ev.target);
const checked = checkbox.prop("checked");
if (target.is("#ok")) {
layer.hide().off();
resolve({ confirmed: true, checked });
} else if (target.is("#cancel")) {
layer.hide().off();
resolve({ confirmed: false, checked });
}
});
});
}
jsConfirm์ ์ด์ Promise ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค. ์ฌ์ฉ์์ ์๋ต์ ๊ฐ์ฒด๋ก ๋ง๋ค์ด resolve๋ฅผ ์คํํ๊ณ ์๋ค. Promise์ ๊ธฐ๋ณธ ์คํ์ ๊ถ๊ธํ ๋ ์๋ ์๋ ๋งํฌ๋ฅผ ํ์ธ ๋ฐ๋๋ค.
์ด๋ฅผ ๋ฐํ์ผ๋ก ์ค๋ณตํญ๋ชฉ ์ฒดํฌ๋ฅผ Promise๋ก ๋ฆฌํฉํ ๋ง ํด ๋ณด์. ๋ชฉ๋ก์ ๋ํด ์์ฐจ์ ์ผ๋ก jsConfirm์ ํธ์ถํด์ผ ํ๋ฏ๋ก Promise๋ฅผ ์ด์ด ๋ถ์ด๋ ๋ฐฉ๋ฒ์ผ๋ก ๊ตฌํํ๋ค. ์ด ๋ฐฉ๋ฒ์ ๋ฐฐ์ด์ ์์์ ๋ํด์ Promise๋ฅผ ์์ฐจ ์ฒ๋ฆฌํ ๋ ์ ์ฉํ๋ค.
let resolved = [];
dupList
.reduce((promise, item, idx) => {
return promise.then(() => {
return jsConfirm().then(({ confirmed, checked }) => {
if (confirmed) {
// A 'ํ์ธ'
resolved.push(item);
}
idx += 1;
if (checked) {
if (confirmed) {
// B '์ดํ ๋ชจ๋ ํญ๋ชฉ์ ์ ์ฉ', 'ํ์ธ'
resolved = [...resolved, ...dupList.slice(idx)];
} else {
// C '์ดํ ๋ชจ๋ ํญ๋ชฉ์ ์ ์ฉ', '์ทจ์'
}
// Promise ์ฒด์ธ์ ์์ ํ ํ์ถํ๊ธฐ ์ํจ
throw new Error("checked");
}
});
});
}, Promise.resolve())
.then(() => {
// D ๋ชจ๋ ํญ๋ชฉ ์๋ฃ
console.log(resolved);
});
์ ๋ณด๋ค ํจ์ฌ ๋ณด๊ธฐ ์ฌ์์ก๋๊ฐ? ๊ฐ์ธ์ ์ผ๋ก ํฌ๊ฒ ๋ฌ๋ผ์ง ์ ์ ์์ด ๋ณด์ธ๋ค. ์ฌ๊ท ์ฝ๋๊ฐ ์์ด์ง๊ณ ๋ชจ๋ ํญ๋ชฉ์ ์๋ฃ ์ฒ๋ฆฌ๋ฅผ ๋งจ ๋ง์ง๋ง then
์ฒด์ธ์์ ํ ์ ์๋ค๋ ๊ฒ๊ณผ, catch
๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ๋์๋จ ์ ์ ๋์ด๋ค. ์ด catch
๋ Promise ์ฒด์ธ์ ์ด๋ ๊ณณ์์๋ผ๋ ๋ฐ์ํ ์ค๋ฅ๊ฐ ๋ชจ์ด๋ฏ๋ก ์ฌ์ฉ์ ์ค๋ฅ, XHR์ค๋ฅ ๋ฑ๋ฑ์ ํ ๊ณณ์์ ์ฒ๋ฆฌํ ์ ์๊ฒ ๋ ๊ฒ์ด๋ค.
์ฌ์ค ๊ทธ๋ฆฌ ์์๋ณด๊ธฐ ์ฌ์ด ํธ์ ์๋๋ค. Promise ์์ฒด์ ์ดํด๊ฐ ์๋ ๊ฐ๋ฐ์์๊ฒ๋ ๋๋์ฑ ๊ทธ๋ด ๊ฒ์ด๊ณ ๋ฌด์๋ณด๋ค๋ ์์ ์ด์ผ๊ธฐํ๋ '๋น๋๊ธฐ ์ฝ๋๋ฅผ ๋๊ธฐ ์ฝ๋์ฒ๋ผ ์ธ ์ ์๋ค'๋ผ๋ ์ด์ผ๊ธฐ๋ฅผ ์ค๋ช ํ ์ ์๋ค.
Generator ๋ช ์ธ๊ฐ ๋์ค๊ธฐ ์ ๊น์ง๋ง ํด๋ ์ด ๋ฐฉ๋ฒ์ด ์ต์ ์ด์์ง๋ง ์ง๊ธ์ ์๋๋ค. ๋ฆฌํฉํ ๋งํด ๋ณด์.
1๋ถ์์ ์ฌ์ฉํ๋ Promise Runner์ ์ด์ ์ฅ์์ ๊ตฌํํ๋ Promise base jsConfirm์ ๊ทธ๋๋ก ์ฌ์ฉํ๋ค.
run(function*() {
let resolved = [];
for (let i = 0, len = dupList.length; i < len; i += 1) {
const item = dupList[i];
const { confirmed, checked } = yield jsConfirm();
if (confirmed) {
// A ํ์ธ
resolved.push(item);
}
if (checked) {
if (confirmed) {
// B '์ดํ ๋ชจ๋ ํญ๋ชฉ์ ์ ์ฉ', 'ํ์ธ'
resolved = [...resolved, ...dupList.slice(i + 1)];
} else {
// C '์ดํ ๋ชจ๋ ํญ๋ชฉ์ ์ ์ฉ', '์ทจ์'
}
break;
}
}
// D ๋ชจ๋ ํญ๋ชฉ ์๋ฃ
console.log(resolved);
});
Promise Runner ํจ์ ๋๋ถ์ jsConfirm
๊ฐ ๋ฐํํ๋ Promise์ ์๋ต์ด ์ฌ ๋๊น์ง ์ผ์ ์ ์งํ ์ ์๊ฒ ๋์๋ค. ๊ทธ ๋๋ถ์ ์ผ๋ฐ์ ์ธ for ๋ฐ๋ณต๋ฌธ์ผ๋ก๋ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ํ ์ ์๊ฒ ๋์๋ค.
์ฝ๋์ ์ฃผ์ ํ๊ธฐ๋ A, B, C, D๋ก ๋๋์ด ์์ง๋ง, ๊ฒฐ๊ณผ์ ์ผ๋ก D๋ก ์๋ ดํ๊ธฐ ๋๋ฌธ์ [ํ์ผ ๋ฐ ํด๋ ์ด๋] API๋ D ์์น์์ ์ผ๊ด์ ์ผ๋ก ์์ฒญํ ์ ์๋ค. ๊ณ์ํด์ API ํธ์ถ๊น์ง ๊ตฌํํด ๋ณธ๋ค.
function* moveObjects(destId, targetIdList) {
// [์ด๋ฆ ์ค๋ณต ํ์ธ] API ํธ์ถ
const dupList = yield axios.get("/api/check-duplicate?dest...");
// [์ค๋ณต๋๋ ๋ชจ๋ ํญ๋ชฉ์ ์ฌ์ฉ์ ์๋ต ์์ง]
let resolved = [];
for (let i = 0, len = dupList.length; i < len; i += 1) {
const item = dupList[i];
const { confirmed, checked } = yield jsConfirm();
if (confirmed) {
// A ํ์ธ
resolved.push(item);
}
if (checked) {
if (confirmed) {
resolved = [...resolved, ...dupList.slice(i + 1)];
}
break;
}
}
// [๊ฐ์ฒด ์ด๋] API ํธ์ถ
yield axios.post("/api/move", { resolved /* request data */ });
}
์๊ตฌ์ฌํญ์ moveObjects Generator ํจ์ ํ๋๋ก ๊ตฌํํ๋ค. Callback, Promise๋ณด๋ค ํจ์ฌ ๊ฐ๋จํ๊ฒ ๊ตฌํํ ์ ์์๋ค. ์ค๋ฅ ์ฒ๋ฆฌ๋ ์ด๋ป๊ฒ ํ ๊น? ๊ทธ๋ฅ try...catch
๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค. ์คํ์ ๋ณด์ฅํ๋ finally
๋ ๋ค์ด๋ค.
function* moveObjects(destId, targetIdList) {
try {
/* ๊ตฌํ */
} catch (err) {
// API ํธ์ถ ์ค๋ฅ ์ฒ๋ฆฌ
// ๊ธฐํ ์ค๋ฅ ์ฒ๋ฆฌ
} finally {
// ํ์์ ๊ฒฝ์ฐ ๊ตฌํ (React์ ๊ฒฝ์ฐ ์ด์ ์ํ๋ก ๋ณต์ ๋ฑ...)
}
}
์ฌ์ค ์์ ์๋ฌ ์ฒ๋ฆฌ๋ฅผ ํ๋ ค๋ฉด run ์ฝ๋๋ ์ฝ๊ฐ ์์ ์ด ํ์ํ๋ค. 1๋ถ์์ ์๊ฐํ๋ Promise Runner๋ฅผ ์์ ํด ๋ณด์
function run(gen) {
const iter = gen();
(function iterate({ value, done }) {
if (done) {
return value;
}
if (value.constructor === Promise) {
value
.then(data => iterate(iter.next(data)))
.catch(err => iter.throw(err)); // ์ฌ๊ธฐ๊ฐ ์ถ๊ฐ๋ ์ฝ๋
} else {
iterate(iter.next(value));
}
})(iter.next());
}
์๋ฌ ์ฒ๋ฆฌ ์ฝ๋๋ ๊ฐ์ ์ค์ฝํ ์ฝ๋๊น์ง๋ง ์ ํจํ๋ค. ๋น๋๊ธฐ ์ฝ๋๋ ํ์ฌ ์ค์ฝํ๋ณด๋ค ์ดํ ์ค์ฝํ ๋๋ ํ๋ ์์์ ์คํ๋๊ธฐ ๋๋ฌธ์ ๋น๋๊ธฐ ์ฝ๋ ๋ฐ๊นฅ์์ ์๋ฌ๋ฅผ ์ก์ผ๋ ค๋ฉด ์ง์ ์ ๋ฌํด์ฃผ์ด์ผ ํ๋ค.
try {
jQuery.ajax({
success: () => {
//์ฌ๊ธฐ์ ์ค๋ฅ๊ฐ ๋ฐ์ํด๋
}
});
} catch (err) {
// ์ฌ๊ธฐ์ ์ก์ ์ ์๋ค.
}
run
๋ด๋ถ์ iterate
์คํ ํ์ด๋ฐ๊ณผ Promise ์ฒ๋ฆฌ ์ฝ๋๊ฐ ๊ทธ ์๋ค. ๊ทธ๋์ Promise์ ์ค๋ฅ๋ฅผ ์ง์ Iterator์ throw
๋ก ์ ๋ฌํ๋๋ก ์์ ํ ๊ฒ์ด๋ค. ์ด์ ์ค๋ฅ ์ฒ๋ฆฌ๋ฅผ ํฌํจํด Generator๋ฅผ ๋ค๋ฃฐ ์ ์๊ฒ ๋์๋ค.
์๋น์ค ์ง์ ๋ฒ์๊ฐ Chrome, Firefox ์ต์ ๋ฒ์ ์ด๋ฉด ๋ฐ๋ก ์ฌ์ฉํ ์ ์๋ค. ํ์ง๋ง ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ ํธ๋์คํ์ผ๋ฌ๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค. 8/8์ผ ํ์ฌ Generator๋ฅผ es5๊ธฐ๋ฐ ์ฝ๋๋ก ๋ณํํด์ฃผ๋ ํธ๋์คํ์ผ๋ฌ๋ Facebook ์ regenerator๊ฐ ์ ์ผํ๋ค. ์ด regenerator๋ runtime๊ณผ transpiler๋ก ๊ตฌ์ฑ๋์ด ์๋๋ฐ runtime์ ์์ถ ์ 1KB ๋ฏธ๋ง์ด๋ฏ๋ก ๋ถ๋ด์ด ์๋ค.
์ด๋ฏธ ์๋ฒ์ ๋ง์ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๊ฐ ์๊ณ ์ด ์ค Generator๋ฅผ ์ ์ฉํ๊ณ ์ถ์ ์ฝ๋๊ฐ ์๋ค๊ณ ๊ฐ์ ํ์.
// ์๋น์ค ์ฝ๋
<script>
// ๋ค์์คํ์ด์ค ์ค์
window.ne = { toastDrive: {} };
</script>
<script src="src/js/generators.js"></script>
<script>
ne.toastDrive.logList(["a", "b"]);
</script>
์๋ generators.src.js
๋ ํธ๋์คํ์ผ๋๊ธฐ ์ Generator ํจ์๋ค์ด ๋ชจ์ฌ์๋ ํ์ผ์ด๋ค.
// src/js/generators.src.js
function run(gen) {/* runner */}
ne.toastDrive.logList = function(dupList) {
run(function*() {
for (let item of dupList) {
console.log(item);
yield item;
}
});
};
์ด์ regenerator๋ฅผ ์ด์ฉํด ์ด ํ์ผ์ ํธ๋์คํ์ผํ๋ค.
// regenerator ์ค์น
npm install -g regenerator
// --include-runtime์ ํตํด ์์กด ๋ชจ๋์ ํฌํจํ์ฌ ํธ๋์คํ์ผ
regenerator --include-runtime src/js/generators.src.js > src/js/generators.js
์ด๋ ๊ฒ ํ๋ฉด ๊ธฐ์กด ์ฝ๋๋ฅผ ์ ์งํ๋ฉด์๋ ํ์ํ ๋ถ๋ถ์๋ง Generator๋ฅผ ์ฌ์ฉํ ์ ์๋ค. ์ regenerator์คํ ์คํฌ๋ฆฝํธ๋ฅผ ๋ฐฐํฌ ์ ์๋์ผ๋ก ์คํํ๋๋ก ํ๋ฉด ์๋์ผ๋ก ๋ฐฐํฌ ์ ์คํํ์ง ์์๋ ๋๋ค.
Generator๋ฅผ ์ฌ์ฉํ๋ฉด '๋น๋๊ธฐ ์ฝ๋๋ฅผ ๋๊ธฐ ์ฝ๋์ฒ๋ผ' ์์ฑํ ์ ์๋ค. ๋ณต์กํ ๋น๋๊ธฐ ํ๋ฆ์ ์์๋ณด๊ธฐ ์ฝ๊ฒ ์์ฑํ ์ ์๊ณ ์ด๋ ํ๋ฆ์ด ๋ณต์กํ๋ฉด ๋ณต์กํ ์๋ก ๋น์ ๋ฐํ๋ค.
Promise, Generator, BabelJS ์ ๊ฐ๋ ๊ณผ ์ฌ์ฉ๋ฒ์ ์ตํ์ผ ํ์ง๋ง. ์ถฉ๋ถํ ๊ทธ๋ด๋งํ ๊ฐ์น๊ฐ ์๋ค. ๋ง์ฝ ์กฐ๊ธ ๋ ์์ฌ์ด ์๋ค๋ฉด ์ด ๊ธ์์ ๊ฐ๋ตํ๊ฒ ๋ค๋ฃจ์๋ Callback, Promise, Generator ์์์ ํจํด์ ๋ฑ์ฅ ๋ฐฐ๊ฒฝ๊ณผ ๋จ์ , ๋ค์ ๋ฐฉ๋ฒ์ด ๊ฐ์ ธ๋ค์ฃผ๋ ์ด์ ์ ํ์ ํ๋ค๋ฉด ์ด๋ค JavaScript ์๊ตฌ์ฌํญ๋ ์ด๋ ต์ง ์๊ฒ ํด๊ฒฐํ ์ ์๊ฒ ๋ ๊ฒ์ด๋ค.