Skip to content

Node.js util 模块

util 是 Node.js 内置的工具类 API 集合。

util.promisify — 回调转 Promise

将回调风格的 API 转为 Promise 风格:

js
import { exec } from 'node:child_process'
import util from 'node:util'

const execPromise = util.promisify(exec)
const { stdout, stderr } = await execPromise('node -v')

原理(简化实现):

js
const promisify = (original) => {
  return (...args) => {
    return new Promise((resolve, reject) => {
      original(...args, (err, ...values) => {
        if (err) return reject(err)
        if (values.length > 1) {
          resolve({ '0': values[0], '1': values[1] })  // 简化版
        } else {
          resolve(values[0])
        }
      })
    })
  }
}

Node.js 内部通过 kCustomPromisifyArgsSymbol 记录多返回值的 key(如 stdout/stderr),该 Symbol 未对外开放。

util.callbackify — Promise 转回调

promisify 相反,将 Promise 函数转为回调风格:

js
import util from 'node:util'

const fn = (type) => type === 1 ? Promise.resolve('ok') : Promise.reject('error')

const callback = util.callbackify(fn)
callback(1, (err, val) => console.log(err, val))  // null 'ok'
callback(0, (err, val) => console.log(err, val))  // 'error' undefined

原理(简化实现):

js
const callbackify = (fn) => {
  return (...args) => {
    const callback = args.pop()  // 回调函数总是在最后一个
    fn(...args).then(res => callback(null, res)).catch(err => callback(err))
  }
}

util.format — 格式化字符串

类似 C 语言的 printf

js
util.format('%s-----%s %s/%s', 'foo', 'bar', 'xm', 'zs')
// 'foo-----bar xm/zs'

util.format(1, 2, 3)  // 无格式化占位符时用空格分隔
// '1 2 3'
占位符转换类型
%sString
%dNumber
%iparseInt(value, 10)
%fparseFloat(value)
%jJSON(循环引用替换为 '[Circular]'
%oObject(含不可枚举属性+代理)
%OObject(不含不可枚举属性)
%%单个 %