基本使用

将 callback 转为 promise 对象,首先要确保这个 callback 为一个错误优先的回调函数,即 (err, value) => ... err 指定一个错误参数,value 为返回值。

  1. const { promisify } = require('util');
  2. const readFilePromisify = util.promisify(fs.readFile); // 转化为 promise
  3. readFilePromisify('text.txt', 'utf8')
  4. .then(result => console.log(result)) // Nodejs Callback 转 Promise 对象测试
  5. .catch(err => console.log(err));

util.promisify.custom 基本使用

  1. const util = require('util');
  2. function doSomething(foo, callback) {
  3. // ...
  4. }
  5. // 利用 util.promisify.custom 这个 key 自定义 promisify 行为
  6. doSomething[util.promisify.custom] = (foo) => {
  7. return getPromiseSomehow();
  8. };
  9. // 调用 util.promisify 方法
  10. const promisified = util.promisify(doSomething);
  11. // 返回的 promisified 就是刚才自定义的 doSomething[util.promisify.custom] 函数
  12. console.log(promisified === doSomething[util.promisify.custom]);
  13. // prints 'true'
  14. const fs = require('fs');
  15. fs.readFile[util.promisify.custom] = () => {
  16. return Promise.reject('该文件暂时禁止读取');
  17. }
  18. const readFilePromisify = util.promisify(fs.readFile);
  19. readFilePromisify('text.txt', 'utf8')
  20. .then(result => console.log(result))
  21. .catch(err => console.log(err)); // 该文件暂时禁止读取

实现

  1. const kCustomPromisifiedSymbol = Symbol('util.promisify.custom');
  2. promisify.custom = kCustomPromisifiedSymbol;
  3. function promisify(original) {
  4. // 保证 promisify 处理仅对函数生效
  5. if (typeof original !== 'function') {
  6. throw new Error('the original argument must be of type Function.Received type undefined');
  7. }
  8. if (original[kCustomPromisifiedSymbol]) {
  9. const fn = original[kCustomPromisifiedSymbol];
  10. if (typeof fn !== 'function') {
  11. throw new Error('The "mayJunPromisify.custom" property must be of type Function. Received type number');
  12. }
  13. return Object.defineProperty(fn, kCustomPromisifiedSymbol, {
  14. value: fn,
  15. enumerable: false,
  16. writable: false,
  17. configurable: true
  18. })
  19. }
  20. // 将传入的 original 函数 promisify 的关键处理逻辑,
  21. // 此时的 fn 即为 promisify 化后的 original 结果函数
  22. function fn(...args) {
  23. return new Promise((resolve, reject) => {
  24. try {
  25. original.call(this, ...args, (err, result) => {
  26. if (err) {
  27. reject(err);
  28. } else {
  29. resolve(result);
  30. }
  31. })
  32. } catch(err) {
  33. reject(err);
  34. }
  35. })
  36. }
  37. return fn;
  38. }

参考资料

  1. nodejs promisify 实现
  2. Node.js 源码解析 util.promisify 如何将 Callback 转为 Promise