基本使用
将 callback 转为 promise 对象,首先要确保这个 callback 为一个错误优先的回调函数,即
(err, value) => ...
err 指定一个错误参数,value 为返回值。
const { promisify } = require('util');
const readFilePromisify = util.promisify(fs.readFile); // 转化为 promise
readFilePromisify('text.txt', 'utf8')
.then(result => console.log(result)) // Nodejs Callback 转 Promise 对象测试
.catch(err => console.log(err));
util.promisify.custom 基本使用
const util = require('util');
function doSomething(foo, callback) {
// ...
}
// 利用 util.promisify.custom 这个 key 自定义 promisify 行为
doSomething[util.promisify.custom] = (foo) => {
return getPromiseSomehow();
};
// 调用 util.promisify 方法
const promisified = util.promisify(doSomething);
// 返回的 promisified 就是刚才自定义的 doSomething[util.promisify.custom] 函数
console.log(promisified === doSomething[util.promisify.custom]);
// prints 'true'
const fs = require('fs');
fs.readFile[util.promisify.custom] = () => {
return Promise.reject('该文件暂时禁止读取');
}
const readFilePromisify = util.promisify(fs.readFile);
readFilePromisify('text.txt', 'utf8')
.then(result => console.log(result))
.catch(err => console.log(err)); // 该文件暂时禁止读取
实现
const kCustomPromisifiedSymbol = Symbol('util.promisify.custom');
promisify.custom = kCustomPromisifiedSymbol;
function promisify(original) {
// 保证 promisify 处理仅对函数生效
if (typeof original !== 'function') {
throw new Error('the original argument must be of type Function.Received type undefined');
}
if (original[kCustomPromisifiedSymbol]) {
const fn = original[kCustomPromisifiedSymbol];
if (typeof fn !== 'function') {
throw new Error('The "mayJunPromisify.custom" property must be of type Function. Received type number');
}
return Object.defineProperty(fn, kCustomPromisifiedSymbol, {
value: fn,
enumerable: false,
writable: false,
configurable: true
})
}
// 将传入的 original 函数 promisify 的关键处理逻辑,
// 此时的 fn 即为 promisify 化后的 original 结果函数
function fn(...args) {
return new Promise((resolve, reject) => {
try {
original.call(this, ...args, (err, result) => {
if (err) {
reject(err);
} else {
resolve(result);
}
})
} catch(err) {
reject(err);
}
})
}
return fn;
}