Need Help With Promisification

Hello. I am currently stuck on this lesson on Promisification. It is not very long. Literally a page, but I am struggling to understand all the little details.

Here is the callback Version of loadScript()

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`));

  document.head.append(script);
}

And here is the promisified version loadScriptPromise()

let loadScriptPromise = function(src) {
  return new Promise((resolve, reject) => {
    loadScript(src, (err, script) => {
      if (err) reject(err);
      else resolve(script);
    });
  });
};

Question #1
When loadScript() is called inside the returned Promise, are we still using script.onerror and script.onload to determine whether reject() or resolve() is called? Is the “error first” callback style generally only used with .onload and .onerror?

Question #2
What will be accomplished by script.onload = () => callback(null, script) and resolve(script)? The script has already been appended to the page. Is it returning something or doing something further with the script? Is it simply just to return a promise and make it chainable with .then()? And why is script the result of resolve()?

Here is a promisify() function that allows any function to become a Promise.

function promisify(f) {
  return function (...args) { // return a wrapper-function
    return new Promise((resolve, reject) => {
      function callback(err, result) { // custom callback for f
        if (err) {
          reject(err);
        } else {
          resolve(result);
        }
      }

      args.push(callback); // append custom callback to f args

      f.call(this, ...args); // call the original function
    });
  };
}

Question #3
The function f that we promisify can accept (...args) as a parameter because of the wrapper, but those (...args) are never used at all. Are they? And shouldn’t the number of arguments affect the function?

Question #4
What is the custom callback for? It is given arguments err and result, but we don’t even know if the function being promisified has err and result to begin with. Does the promisified function f obtain arguments err and result because we .push() the callback() to args?

And I have no idea what the following means.

But what if the original f expects a callback with more arguments callback(err, res1, res2, ...)?

We can improve our helper. Let’s make a more advanced version of promisify.

When called as promisify(f) it should work similar to the version above.

When called as promisify(f, true), it should return the promise that resolves with the array of callback results. That’s exactly for callbacks with many arguments.

Any help understanding this would be greatly appreciated, as I am completely lost. I do not understand where arrayOfResults in the usage comes from. I also still do not understand how the callback() function connects with the promisified function.

// 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) { // custom callback
        if (err) {
          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(arrayOfResults => ..., err => ...);

I know that was quite a bit. Thank you for taking the time to read this post.

Oh my sweet Baby Jesus I think I get it.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.