# Promisification Promisification -- is a long word for a simple transform. It's conversion of a function that accepts a callback into a function returning a promise. In other words, we create a wrapper-function that does the same, internally calling the original one, but returns a promise. Such transforms are often needed in real-life, as many functions and libraries are callback-based. But promises are more convenient. So it makes sense to promisify those. For instance, we have `loadScript(src, callback)` from the chapter . ```js run function loadScript(src, callback) { let script = document.createElement('script'); script.src = src; script.onload = () => callback(null, script); script.onerror = () => callback(new Error(`Script load error for ${src}`)); document.head.append(script); } // usage: // loadScript('path/script.js', (err, script) => {...}) ``` Let's promisify it. The new `loadScriptPromise(src)` function will do the same, but accept only `src` (no callback) and return a promise. ```js let loadScriptPromise = function(src) { return new Promise((resolve, reject) => { loadScript(src, (err, script) => { if (err) reject(err) elsee resolve(script); }); }) } // usage: // loadScriptPromise('path/script.js').then(...) ``` Now `loadScriptPromise` fits well in our promise-based code. As we can see, it delegates all the work to the original `loadScript`, providing its own callback that translates to promise `resolve/reject`. As we may need to promisify many functions, it makes sense to use a helper. That's actually very simple -- `promisify(f)` below takes a to-promisify function `f` and returns a wrapper function. That wrapper does the same as in the code above: returns a promise and passes the call to the original `f`, tracking the result in a custom callback: ```js function promisify(f) { return function (...args) { // return a wrapper-function return new Promise((resolve, reject) => { function callback(err, result) { // our custom callback for f if (err) { return reject(err); } else { resolve(result); } } args.push(callback); // append our custom callback to the end of arguments f.call(this, ...args); // call the original function }); }; }; // usage: let loadScriptPromise = promisify(loadScript); loadScriptPromise(...).then(...); ``` Here we assume that the original function expects a callback with two arguments `(err, result)`. That's what we meet most often. Then our custom callbacks is exactly in the right format, and `promisify` works great for such case. But what is the original `f` expects a callback with more arguments `callback(err, res1, res2)`? Here's a modification of `promisify` that returns an array of multiple callback results: ```js // promisify(f, true) to get array of results function promisify(f, manyArgs = false) { return function (...args) { return new Promise((resolve, reject) => { function *!*callback(err, ...results*/!*) { // our custom callback for f if (err) { return reject(err); } else { // resolve with all callback results if manyArgs is specified *!*resolve(manyArgs ? results : results[0]);*/!* } } args.push(callback); f.call(this, ...args); }); }; }; // usage: f = promisify(f, true); f(...).then(err => ..., arrayOfResults => ...) ``` In some cases, `err` may be absent at all: `callback(result)`, or there's something exotic in the callback format, then we can promisify such functions manually. There are also modules with a bit more flexible promisification functions, e.g. [es6-promisify](https://github.com/digitaldesignlabs/es6-promisify). In Node.js, there's a built-in `util.promisify` function for that. ```smart Promisification is a great approach, especially when you use `async/await` (see the next chapter), but not a total replacement for callbacks. Remember, a promise may have only one result, but a callback may technically be called many times. So promisification is only meant for functions that call the callback once. Furhter calls will be ignored. ```