[Javascript] promisify函数

前言

随着Promise的广泛使用,我们习惯于将一般的使用回调的函数,转为返回Promise对象的函数,以供书写同步代码。
bluebird库提供了快速转换普通函数的方法:bluebird.Promise.promisify(),但是其内部设计用来支持回调函数第一个参数为err对象的标准范式,不适用于自定义的特别函数。
这里提供了一个优化的promisify(),可以通过额外参数支持特别类型的函数。

声明

promisify(fn, callbackErr, reverse)

  • fn <function> 被包装的函数
  • callbackErr <boolean> (default:true) fn的回调函数参数,其第一个参数是否为err对象
  • reverse <boolean> (default:false) fn的回调函数参数,是否是第一个参数(如setTimeout)

源码

function promisify(fn, callbackErr=true, reverse=false) {
  if ({}.toString.call(fn) !== '[object Function]') throw new TypeError('Only normal function can be promisified');
  return function (...args) {
    return new Promise((resolve, reject) => {
      const callback = function (...args) {
        if (!callbackErr) {
          if (args.length === 1) return resolve(args[0]);
          return resolve(args);
        }
        const err = args.shift();
        const rest = args;
        if ({}.toString.call(err) === '[object Error]') return reject(err);
        if (rest.length === 1) return resolve(rest[0]);
        return resolve(rest);
      };
      try {
        if (reverse === true) fn.apply(null, [callback, ...args]);
        else fn.apply(null, [...args, callback]);
      } catch (err) {
        reject(err);
      }
    });
  }
}

使用

// 系统函数
const lstat = promisify(require('fs').lstat);
lstat('./index.js')
  .then((stats) => {
    console.log(stats)
  })
  .catch(err => console.warn('Catch error:', err));

// 自定义函数 
function foo(a, b, cb) {
  if(cb) cb(a+b);
}
const fooP = promisify(foo, false);
fooP(1, 2)
  .then(res => console.log('res', res))
  .catch(err => console.warn('Catch error:', err));

// setTimeout
const wait = promisify(setTimeout, true, true);
wait(1000).then(() => console.log('1秒后打印'));

// 方法,需要bind对象
const sqlite3 = require('sqlite3').verbose();
const db = new sqlite3.Database(':memory:');
db.allP = promisify(db.all.bind(db)); 
db.allP('SELECT * FROM test').then(rows => console.log(rows));
    原文作者:平仄_pingze
    原文地址: https://www.jianshu.com/p/409e391d6d55
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞