프로미스화 콜백을 받은 함수를 프라미스를 반환하는 함수로 바꾸는 것을 ‘프라미스화(promisification)’ 이라고 한다.
콜백 예시
1 2 3 4 5 6 7 8 9 10 11 12 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); }
이제 이 콜백을 프로미스화 할 것임. 해당 함수는 콜백을 인수로 받지 않고 src만 인수로 받도록 함.
1 2 3 4 5 6 7 8 9 10 11 let loadScriptPromise = function (src ) { return new Promise ((resolve, reject ) => { loadScript(src, (err, script ) => { if (err) reject(err); else resolve(script); }) }) }
loadScriptPromise
는 loadScript
에 모든 일을 위임한다.
그런데 실무에서는 여러 함수를 프라미스화 해야 할 것이다. 래퍼 함수를 만들 도록 한다. 프라미스화를 적용할 함수 f를 받고 래퍼 함수를 반환하는 함수 promisefy(f)
를 만든다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 function promisify (f ) { return function (...args ) { return new Promise ((resolve, reject ) => { function callback (err, result ) { if (err) { reject(err); } else { resolve(result); } } args.push(callback); f.call(this , ...args); }); }; }; let loadScriptPromise = promisify(loadScript);loadScriptPromise(...).then(...);
함수 f
가 두 개를 초과하는 인수를 가진 콜백, callback(err, res1, res2, ...)
을 받는 경우?
promisify(f, true)
형태로 호출하면, 프로미스 결과는 콜백의 성공 케이스 (result)를 담은 배열 [res1, res2, ...]
이 된다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 function promisify (f, manyArgs = false ) { return function (...args ) { return new Promise ((resolve, reject ) => { function callback (err, ...results ) { if (err) { reject(err); } else { resolve(manyArgs ? results : results[0 ]); } } args.push(callback); f.call(this , ...args); }); }; }; f = promisify(f, true ); f(...).then(arrayOfResults => ..., err => ...)
es6-promisify
같은 프라미스화를 도화주는 모듈도 있다. 또한, node.js에선 내장 함수 util.promisify
를 사용해 프라미스화를 할 수 있다.