来源:Node.js

util是Node.js内部提供的一系列实用或者工具类型的API,方便快速开发

util.promisify

将具有回调函数的方法改造成promise写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const { exec } = require('node:child_process')
const util = require('node:util')

// 原先的写法
exec('node -v', (err, stdout, stderr) => {
if (err) {
console.log(err)
}
console.log(stdout) // ->v16.16.0
})

// promisify改造后的写法
const execPromise = util.promisify(exec)
// 如果原回调具有多个参数,则res是一个对象;如果原回调具有一个参数,就返回原参数
execPromise('node -v').then(res=> {
console.log(res) // ->{ stdout: 'v16.16.0\r\n', stderr: '' }
}).catch(err => {
console.log(err)
})

原理就是这样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 接收一个具有回调函数参数的函数
const promisify = (fn) => {
// 返回一个新的函数
return (...args) => {
// 返回一个promise
return new Promise((resolve, reject) => {
// 在promise中调用原函数
fn(...args, (err, ...values) => {
if (err) {
reject(err)
}
else if(values && values.length>1) {
let obj = {}
for(let key in values) {
obj[key] = values[key]
}
resolve(obj)
} else {
resolve(values[0])
}
})
})
}
}

但输出的结果却是{ '0': 'v18.16.0\n', '1': '' },即这样无法获取values的key值

因为Node内部使用kCustomPromisifyArgsSymbol这个symbol获取key,但这个symbol没有暴露给用户

util.callbackify

正好相反,将promise改造成回调函数写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const util = require('node:util')

const fn = (type) => {
if (type === 1) {
return Promise.resolve('test')
} else {
return Promise.reject('error')
}
}

const callback = util.callbackify(fn)

callback(1, (err, data) => {
if (err) {
console.log(err)
} else {
console.log(data)
}
})

原理就是这样

1
2
3
4
5
6
7
8
9
const callbackify = (fn) => {
return (...args) => {
let callback = args.pop()
fn(...args).then(
data => callback(null, data),
err => callback(err)
)
}
}

util.format

类似于C语言的printf

1
2
3
4
5
6
const util = require('node:util')

console.log(util.format('Hello, %s!', 'World')) // -> Hello, World!
console.log(util.format('%s - %s', 'Hello', 'World')) // -> Hello - World
// 如果不传入格式化参数,就按空格分开
console.log(util.format(1, 2, 3)) // -> 1 2 3
  • %s:String,用于除BigInt、Object和-0外的所有值
    • BigInt用n表示
    • 没有用户定义的toString函数的对象使用具有选项{ depth: 0, colors: false, compact: 3 }util.inspect()进行检查
  • %d:Number,用于除BigInt和Symbol之外的所有值
  • %i:parseInt(value, 10),用于除BigInt和Symbol之外的所有值
  • %f:parseFloat(value),用于除Symbol之外的所有值
  • %j:JSON,如果参数包含循环引用,则替换为字符串 '[Circular]'
  • %o:Object,具有通用JavaScript对象格式的对象的字符串表示形式
    • 类似于具有选项{ showHidden: true, showProxy: true }util.inspect()
    • 这将显示完整的对象,包括不可枚举的属性和代理
  • %O:Object,具有通用JavaScript对象格式的对象的字符串表示形式
    • 类似于没有选项的util.inspect()
    • 这将显示完整的对象,但不包括不可枚举的属性和代理
  • %c:CSS,此说明符会被忽略,将跳过任何传入的 CSS
  • %%:单个百分号 (‘%’),这不消费参数