nodejs 第十八章 util

util 是Node.js内部提供很多实用工具类型的API,能方便我们快速开发

  • 由于API比较多 这里着重讲解一些常用的API,剩下的部分将以表格的形式总结在最后面

常用util的API

util.promisify

  • util.promisify 将一个遵循常见 Node.js 回调风格的函数(即最后一个参数是回调函数 callback(err, value) 的函数)转换为返回 Promise 的函数。
  • 这样,可以使用现代的异步编程特性,如 async/await,来处理异步操作。

常规写法(回调函数)

  • 下面这串代码是获取Node版本的常规写法
js 复制代码
import { exec } from 'node:child_process'
exec('node -v', (err,stdout)=>{
   if(err){
      return err
   }
   console.log(stdout)
})

promise风格写法

  • 一样的传入参数方式,但在接收返回结果上,从回调函数变成了.then结尾获取
  • 使用util的promisify 改为promise 风格 Promiseify 接受 original一个函数体
js 复制代码
import { exec } from 'node:child_process'
import util from 'node:util'

const execPromise = util.promisify(exec)

//如果返回多个参数,则res就是一个对象,就需要我们通过res.xxx获取对象里的内容
execPromise('node -v').then(res=>{
    console.log(res,'res')
}).catch(err=>{
    console.log(err,'err')
})

实现promiseify原理

  1. 第一步Promiseify是返回一个新的函数
js 复制代码
const promiseify = () => {
   return () => {

  }
}
  1. promiseify接受一个函数,并且在返回的函数才接受真正的参数,然后返回一个promise
js 复制代码
const promiseify = (original) => {
   return (...args) => {
     return new Promise((resolve,reject)=>{
        
     })
  }
}
  1. 调用真正的函数,将参数透传给original,如果失败了就reject,如果成功了,就返回resolve,如果有多个返回一个对象。
js 复制代码
// 定义 promiseify 函数,接收一个名为 original 的函数作为参数
const promiseify = (original) => {
    // 返回一个新的函数,使用 args 参数来接收任意数量的参数
    return (...args) => {
        // 创建并返回一个新的 Promise 对象
        return new Promise((resolve, reject) => {
            // 调用原始函数,传入参数和一个新的回调函数来处理异步完成后的结果
            original(...args, (err, ...values) => {
                // 处理错误情况
                if (err) {
                    // 使用 reject 函数将 Promise 的状态改为 rejected,并返回错误对象
                    return reject(err);
                }
                // 检查回调中是否有多个返回值
                if (values && values.length > 1) {
                    // 如果有多个返回值,创建一个对象来存储这些值
                    let obj = {};
                    // 打印返回的值(主要用于调试)
                    console.log(values);
                    // 遍历 values 数组,并将每个索引和对应的值存储到 obj 对象中
                    for (let key in values) {
                        obj[key] = values[key];
                    }
                    // 使用 resolve 函数将 Promise 的状态改为 fulfilled,并返回 obj 对象
                    resolve(obj);
                } else {
                    // 如果回调中只有一个返回值,直接使用 resolve 函数返回这个值
                    resolve(values[0]);
                }
            });
        });
    }
}
  • 这样可以大致实现但是拿不到values 的key 因为 nodejs内部 没有对我们开放 这个Symbol kCustomPromisifyArgsSymbol

  • 所以输出的结果是 { '0': 'v20.10.0\r\n', '1': '' } 正常应该是 { stdout: 'v20.10.0\n', stderr: '' },但我们拿不到key,就没办法做到完全一样

util.callbackify

util.promisify 相反,util.callbackify 将一个返回 Promise 的函数转换为遵循 Node.js 回调风格的函数。这在需要将基于 Promise 的 API 集成到仅支持回调风格的旧代码库中时非常有用。

js 复制代码
const util = require('node:util')
//fn函数返回的结果是promise,我们要进行改写成回调风格
const fn = (type) =>{
  //自己设置条件,这个需求很宽松.比如在这里我就希望type为1的情况下才是我想要的,则成功,反之失败
  if(type == 1){
    return Promise.resolve('success')
  }else{
    return Promise.reject('err')
  }
}
//使用callbackify进行回调处理
const callback = util.callbackify(fn)

//Node.js 中,使用回调函数的约定是由 Node.js 的 API 设计哲学决定的.遵循了所谓的"错误优先回调"
//主要目的是确保在进行异步操作时,能够优先处理可能出现的错误
callback(1,(err,value)=> {
  console.log(err,value);
})

callbackify原理

js 复制代码
const callbackify = (fn) => {
    return (...args) => {
      // 考虑多个参数的情况,但是回调函数肯定在最后一个,所以使用pop把他(回调函数)取出来
        let callback = args.pop()
        fn(...args).then(res => {
            callback(null, res)
        }).catch(err => {
            callback(err)
        })
    }
}

util.format

util.format 是一个格式化字符串的函数,类似于 C 语言中的 printf 或 Python 中的字符串格式化。它可以将多个参数组合成一个字符串,支持多种占位符,如 %s(字符串)、%d(数字)等。

占位符描述

  • %s - 字符串
  • %d - 整数(使用 %i 也可以得到相同结果)
  • %f - 浮点数
  • %j - JSON(如果转换失败,会替换为 '[Circular]'
  • %o - 对象(带一些附加选项的详细信息)
  • %O - 对象(标准详细信息)
  • %% - 输出一个 % 符号
参数 详细描述
%s 格式化为字符串。对于 BigInt 显示为末尾带 n,对于 -0 显示为 0,普通对象使用 util.inspect(){ depth: 0, colors: false, compact: 3 })。
%d 格式化为整数。BigIntSymbol 类型除外。
%i 格式化为使用 parseInt(value, 10) 的整数。BigIntSymbol 类型除外。
%f 格式化为使用 parseFloat(value) 的浮点数。Symbol 类型除外。
%j 将参数格式化为 JSON 字符串。如果存在循环引用,则显示为 '[Circular]'
%o 显示对象的详细多行表示,包括不可枚举属性和代理({ showHidden: true, showProxy: true }util.inspect())。
%O 显示对象的详细多行表示,但不包括不可枚举属性和代理(无选项的 util.inspect())。
%c 此格式化指令用于 CSS,但在 Node.js 中被忽略。
%% 输出一个百分比符号(%)。不消耗参数。
  • 这个函数的使用方式类似于 C 语言中的 printf 或 Python 中的格式化字符串功能,让开发者能够根据指定格式来组合字符串和其他数据类型
js 复制代码
util.format(format[, ...args])

//format 是一个字符串,包含文本以及一个或多个占位符。
//...args 是与占位符相对应的值。

使用案例

js 复制代码
const util = require('util');

// 基础字符串格式化
console.log(util.format('%s:%s', 'name', 'Alice')); // 输出: 'name:Alice'

// 混合不同类型
console.log(util.format('My name is %s and I am %d years old.', 'Bob', 25)); // 输出: 'My name is Bob and I am 25 years old.'

// JSON 对象
console.log(util.format('User details: %j', { name: 'Carol', age: 30 })); // 输出: 'User details: {"name":"Carol","age":30}'

// 多个对象
console.log(util.format('Data: %o', { foo: 'bar' })); // 输出对象的详细信息

// 浮点数
console.log(util.format('Value: %f', 3.14159265)); // 输出: 'Value: 3.14159265'

// 显示百分比
console.log(util.format('100%% Complete')); // 输出: '100% Complete'
相关推荐
庸俗今天不摸鱼14 分钟前
【万字总结】前端全方位性能优化指南(十)——自适应优化系统、遗传算法调参、Service Worker智能降级方案
前端·性能优化·webassembly
QTX1873015 分钟前
JavaScript 中的原型链与继承
开发语言·javascript·原型模式
黄毛火烧雪下21 分钟前
React Context API 用于在组件树中共享全局状态
前端·javascript·react.js
Apifox32 分钟前
如何在 Apifox 中通过 CLI 运行包含云端数据库连接配置的测试场景
前端·后端·程序员
一张假钞34 分钟前
Firefox默认在新标签页打开收藏栏链接
前端·firefox
高达可以过山车不行35 分钟前
Firefox账号同步书签不一致(火狐浏览器书签同步不一致)
前端·firefox
m0_5937581036 分钟前
firefox 136.0.4版本离线安装MarkDown插件
前端·firefox
掘金一周39 分钟前
金石焕新程 >> 瓜分万元现金大奖征文活动即将回归 | 掘金一周 4.3
前端·人工智能·后端
三翼鸟数字化技术团队1 小时前
Vue自定义指令最佳实践教程
前端·vue.js
Jasmin Tin Wei1 小时前
蓝桥杯 web 学海无涯(axios、ecahrts)版本二
前端·蓝桥杯