ì½ë°±ì ë°ë í¨ì를 íë¼ë¯¸ì¤ë¥¼ ë°ííë í¨ìë¡ ë°ê¾¸ë ê²ì 'íë¼ë¯¸ì¤í(promisification)'ë¼ê³ í©ëë¤.
기ë¥ì 구í íë¤ ë³´ë©´ ì½ë°±ë³´ë¤ë íë¼ë¯¸ì¤ê° ë í¸ë¦¬í기 ë문ì ì½ë°± ê¸°ë° í¨ìì ë¼ì´ë¸ë¬ë¦¬ë¥¼ íë¼ë¯¸ì¤ë¥¼ ë°ííë í¨ìë¡ ë°ê¾¸ë ê² ì¢ì ê²½ì°ê° ì¢ ì¢ ì길 ê²ëë¤.
ì½ë°± ì±í°ìì ì¬ì©íë loadScript(src, callback) ìì를 ì¬ì©í´ íë¼ë¯¸ì¤íì ëí´ ì¢ ë ìì¸í ììë´
ìë¤.
function loadScript(src, callback) {
let script = document.createElement('script');
script.src = src;
script.onload = () => callback(null, script);
script.onerror = () => callback(new Error(`${src}를 ë¶ë¬ì¤ë ëì¤ì ìë¬ê° ë°ìí¨`));
document.head.append(script);
}
// ì¬ì©ë²:
// loadScript('path/script.js', (err, script) => {...})
loadScript(src, callback)를 ì´ì íë¼ë¯¸ì¤íí´ë´
ìë¤. ìë¡ì´ í¨ì loadScriptPromise(src)ë loadScriptì ëì¼íê² ëìíì§ë§ callbackì ì ì¸í srcë§ ì¸ìë¡ ë°ìì¼ íê³ , íë¼ë¯¸ì¤ë¥¼ ë°íí´ì¼ í©ëë¤.
let loadScriptPromise = function(src) {
return new Promise((resolve, reject) => {
loadScript(src, (err, script) => {
if (err) reject(err)
else resolve(script);
});
})
}
// ì¬ì©ë²:
// loadScriptPromise('path/script.js').then(...)
ìë¡ê² 구íí loadScriptPromiseë íë¼ë¯¸ì¤ ê¸°ë° ì½ëì ì ìµíë©ëë¤.
ìììì ë³¼ ì ìë¯ì´, loadScriptPromiseë 기존 í¨ì loadScriptì 모ë ì¼ì ììí©ëë¤. loadScriptì ì½ë°±ì ì¤í¬ë¦½í¸ ë¡ë© ìíì ë°ë¼ ì´í í¹ì ê±°ë¶ìíì íë¼ë¯¸ì¤ë¥¼ ë°íí©ëë¤.
ê·¸ë°ë° ì¤ë¬´ìì í¨ì íëê° ìë ì¬ë¬ ê°ì í¨ì를 íë¼ë¯¸ì¤í í´ì¼ í ê²ëë¤. í¬í¼ í¨ì를 ë§ëë ê² ì¢ì ê² ê°ë¤ì. íë¼ë¯¸ì¤í를 ì ì© í í¨ì f를 ë°ê³ ëí¼ í¨ì를 ë°ííë í¨ì promisify(f)를 ë§ë¤ì´ë´
ìë¤.
promisify(f)ê° ë°ííë ëí¼ í¨ìë ì ììì ëì¼íê² ëìí ê²ëë¤. íë¼ë¯¸ì¤ë¥¼ ë°ííê³ í¸ì¶ì 기존 í¨ì fì ì ë¬íì¬ ì»¤ì¤í
ì½ë°± ë´ì 결과를 ì¶ì í´ì¼ íì£ .
function promisify(f) {
return function (...args) { // ëí¼ í¨ì를 ë°íí¨
return new Promise((resolve, reject) => {
function callback(err, result) { // fì ì¬ì©í 커ì¤í
ì½ë°±
if (err) {
reject(err);
} else {
resolve(result);
}
}
args.push(callback); // ììì ë§ë 커ì¤í
ì½ë°±ì í¨ì fì ì¸ì ëì ì¶ê°í©ëë¤.
f.call(this, ...args); // 기존 í¨ì를 í¸ì¶í©ëë¤.
});
};
};
// ì¬ì©ë²:
let loadScriptPromise = promisify(loadScript);
loadScriptPromise(...).then(...);
ì ììë íë¼ë¯¸ì¤í í í¨ìê° ì¸ìê° ë ê°((err, result))ì¸ ì½ë°±ì ë°ì ê²ì´ë¼ ê°ì íê³ ìì±ëììµëë¤. ìì¤í구 ì´ë° ìí©ì¼ ê²ì´ê³ , 커ì¤í
ì½ë°±ì ì´ ìí©ì ë± ë¤ì´ë§ìµëë¤. promisifyê° ì ëìíë ê²ì ë§í ê²ë ìê² ì£ .
ê·¸ë°ë° í¨ì fê° ë ê°ë¥¼ ì´ê³¼íë ì¸ì를 ê°ì§ ì½ë°±, callback(err, res1, res2, ...)ì ë°ëë¤ë©´ ì´ë¤ ì¼ì´ ë°ìí ê¹ì?
ì´ë° ê²½ì°ë¥¼ ëë¹íì¬ ì¢ ë ì§íí í¬í¼ í¨ì, promisify를 ë§ë¤ì´ ë´
ìë¤. ìë¡ê² ë§ë í¨ì를 promisify(f, true)ííë¡ í¸ì¶íë©´, íë¼ë¯¸ì¤ ê²°ê³¼ë ì½ë°±ì ì±ê³µ ì¼ì´ì¤(results)를 ë´ì ë°°ì´, [res1, res2, ...]ì´ ë©ëë¤.
// ì½ë°±ì ì±ê³µ 결과를 ë´ì ë°°ì´ì ì»ê² í´ì£¼ë promisify(f, true)
function promisify(f, manyArgs = false) {
return function (...args) {
return new Promise((resolve, reject) => {
function callback(err, ...results) { // fì ì¬ì©í 커ì¤í
ì½ë°±
if (err) {
reject(err);
} else {
// manyArgsê° êµ¬ì²´ì ì¼ë¡ ëª
ìëìë¤ë©´, ì½ë°±ì ì±ê³µ ì¼ì´ì¤ì í¨ê» ì´í ìíê° ë©ëë¤.
resolve(manyArgs ? results : results[0]);
}
}
args.push(callback);
f.call(this, ...args);
});
};
};
// ì¬ì©ë²:
f = promisify(f, true);
f(...).then(arrayOfResults => ..., err => ...)
callback(result)ê°ì´ errì´ ìë ííë ì§ê¸ê¹ì§ ì¸ê¸íì§ ìì ííì ì´ìì ì¸ ì½ë°±ë ìì ì ìëë°, ì´ë° ê²½ì°ì í¬í¼ í¨ì를 ì¬ì©íì§ ìê³ ì§ì íë¼ë¯¸ì¤í íë©´ ë©ëë¤.
본 ì±í°ìì ì¤ëª
í í¬í¼ í¨ìë³´ë¤ ë ì ì©í ííì íë¼ë¯¸ì¤í를 ëì주ë í¨ì를 ì ê³µíë 모ëë ë§ìµëë¤. es6-promisifyê° ëíì ì¸ ìì
ëë¤. Node.jsìì ë´ì¥ í¨ì util.promisify를 ì¬ì©í´ íë¼ë¯¸ì¤í를 í ì ììµëë¤.
íë¼ë¯¸ì¤íë ê³§ ë°°ì°ê² ë async/awaitì í¨ê» ì¬ì©íë©´ ë ì¢ìµëë¤. ë¤ë§, ì½ë°±ì ìì í ëì²´íì§ë 못íë¤ë ì¬ì¤ì 기ìµí´ ëì기 ë°ëëë¤.
íë¼ë¯¸ì¤ë íëì ê²°ê³¼ë§ ê°ì§ ì ìì§ë§, ì½ë°±ì ì¬ë¬ ë² í¸ì¶í ì ì기 ë문ì ëë¤.
ë°ë¼ì íë¼ë¯¸ì¤íë ì½ë°±ì ë¨ í ë² í¸ì¶íë í¨ììë§ ì ì©íì기 ë°ëëë¤. íë¼ë¯¸ì¤íí í¨ìì ì½ë°±ì ì¬ë¬ ë² í¸ì¶í´ë, ë ë²ì§¸ë¶í°ë 무ìë©ëë¤.
ëê¸
<code>í그를, ì¬ë¬ ì¤ë¡ 구ì±ë ì½ë를 ì½ì íê³ ì¶ë¤ë©´<pre>í그를 ì´ì©íì¸ì. 10ì¤ ì´ìì ì½ëë plnkr, JSBin, codepen ë±ì ìëë°ì¤ë¥¼ ì¬ì©íì¸ì.