简体   繁体   中英

Node: util.promisify() without callback as final parameter

I'm trying to use util.promisify() to transform a function that uses a callback so I can call it with async/await: https://nodejs.org/dist/latest-v8.x/docs/api/util.html#util_util_promisify_original

So far I've been able to use it with functions that have the callback as the final parameter, as it expects. But I'm getting confused on how to use it when another item is the final parameter.

I have a function that structured like this:

myFunction = function(userID, company, callback, jwt) {
    ....
    return callback(null, results)
}

Since the jwt is the final parameter, how can I use promisify on this and still pass the jwt ? I'd rather not change the structure of the original function because other places are calling it as-is

You can create a new function wrapper around your function that only accepts arguments in a different order in order to move the callback last:

const wrapper = (userID, company, jwt, callback) => 
    myFunction(userID, company, callback, jwt);

const promisified = utils.promisify(wrapper);

For a more generic solution, you can use Lodash's rearg that will change the order of arguments based on the array you give it:

const wrapper = _.rearg(myFunction, [0, 1, 3, 2]);

const promisified = utils.promisify(wrapper);

Working with the function:

myFunction = function(userID, company, callback, jwt) {
    /* ... */
    return callback(null, results)
}

You have four options.

  1. Wrap the function with the arguments in a different order:
util.promisify((userID, company, jwt, callback) => myFunction(userID, company, callback, jwt))
  1. Supply your own promisifier (assuming you are in control of the code)
myFunction[util.promisify.custom] = function (userID, company, jwt) {
  return new Promise((resolve, reject) => {
    const callback = (err, result) => err ? reject(err) : resolve(result);
    myFunction.call(this, userID, company, callback, jwt); 
  });
}

You can then use this with utils.promisify(myFunction) and it will pull your custom implementation.

  1. Redefine it to the nodeback style (callback last)
myFunction = function(userID, company, jwt, callback) {
    /* ... */
    return callback(null, results)
}
  1. Redefine it to coerce types when called (make sure to unit-test this)
myFunction = function(userID, company, callbackOrJwt, jwtOrCallback) {
    const [callback, jwt] = callbackOrJwt !== null && typeof callbackOrJwt === 'object'
      ? [jwtOrCallback, callbackOrJwt]   // possibly called with jwt first
      : [callbackOrJwt, jwtOrCallback];  // possibly called with callback first
    /* ... */
    return callback(null, results)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM