你不知道的 Node.js 工具函数

从类型判断说起

在 JavaScript 中,进行变量的类型校验是一个非常令人头疼的事,如果只是简单的使用 typeof 会到各种各样的问题。

举几个简单的🌰:

console.log(typeof null) // 'object'
console.log(typeof new Array) // 'object'
console.log(typeof new String) // 'object'

后来,大家发现可以使用 Object.prototype.toString() 方法来进行变量类型的判断。

const getTypeString = obj => Object.prototype.toString.call(obj)getTypeString(null) // '[object Null]'
getTypeString('string') //'[object String]'
getTypeString(new String) //'[object String]'

toString() 方法进行代理,可以得到一个类型字符串,我们就可以在这个字符串上面搞事情。

const getTypeString = obj => {return Object.prototype.toString.call(obj)
}
const isType = type => {return obj => {return getTypeString(obj) === `[object ${type}]`}
}const isArray = isType('Array') // 该方法一般通过 Array.isArray 代替const isNull = isType('Null')
const isObject = isType('Object')
const isRegExp = isType('RegExp')
const isFunction = isType('Function')
const isAsyncFunction = isType('AsyncFunction')
isNull(null) // true
isObject({}) // true
isRegExp(/\w/) // true
isFunction(() => {}) // true
isAsyncFunction(async () => {}) // true

But,在 Node.js 中,内部其实是有一组用来判断变量类型的 api 的。而且功能异常丰富,除了基础类型的判断,还支持判断 Promise 对象、Date 对象、各种ArrayBuffer。

const types = require('util/types')types.isDate(new Date) // true
types.isPromise(new Promise(() => {})) // true
types.isArrayBuffer(new ArrayBuffer(16)) // true

严格相等

在 JavaScript 中,对象、数组等变量在判断相等的过程中,如果用 === 通常只会判断这两个变量是否指向同一内存地址。如果想判断对象的键对应的所有值是否相等,需要对两个对象进行遍历。在 util 中,也提供了一个方法可以用来判断两个对象是否严格相等:util.isDeepStrictEqual(val1, val2)

const util = require('util')const val1 = { name: 'shenfq' }
const val2 = { name: 'shenfq' }console.log('val1 === val2', val1 === val2) // false
console.log('isDeepStrictEqual', util.isDeepStrictEqual(val1, val2)) // true
e8b68cb738241b57f6678fed556c9951.png

该方法同样可以用来判断数组,是否严格相等:

const util = require('util')const arr1 = [1, 3, 5]
const arr2 = [1, 3, 5]console.log('arr1 === arr2', arr1 === arr2) // false
console.log('isDeepStrictEqual', util.isDeepStrictEqual(arr1, arr2)) // true
131c8fd990032a923bce476fce33fea2.png

Error First & Promise

早期的 Node API 都是 Error First 风格的,也就是所有的异步函数都会接受一个回调函数,该回调的一个参数为 error 对象,如果正常返回 error 对象为 null,后面的参数为成功响应的结果。

// 下面是一个读取文件的示例
const fs = require('fs')
fs.readFile('nginx.log', (error, data) => {if (error) {// 读取文件失败console.error(error)return}// 读取文件成功,打印结果console.log(data)
})

在 Node 8 发布的时候,新增了一个 promisify 接口,用于将 Error First 风格的 API 转为 Promise API。

const fs = require('fs')
const util = require('util')const readFile = util.promisify(fs.readFile)
readFile('./2021-11-11.log', { encoding: 'utf-8' }).then(text => console.log(text)) .catch(error => console.error(error))
3acf7b7e9e0f386cacec6333504edcea.png

不过,后来也有很多人觉得这些原生 API 支持 Promise 的方式太过繁琐,每个 API 都需要单独的包装一层 promisify 方法。在 Node 10 发布的时候,原生模块都新增了一个 .promises 属性,该属性下的所有 API 都 Promise 风格的。

const fs = require('fs').promises
fs.readFile('./2021-11-11.log', { encoding: 'utf-8' }).then(text => console.log(text)) .catch(error => console.error(error))
8ee9ab9ea61daefbd852cb05e95ab776.png

注意:Node 14 后,promises API 又新增了一种引入方式,通过修改包名的方式引入。

const fs = require('fs/promises')
fs.readFile('./2021-11-11.log', { encoding: 'utf-8' }).then(text => console.log(text)) .catch(error => console.error(error))
ca6f709962a6b2ad381137e1b41a9605.png

除了将 Error First 风格的 API 转为 Promise API,util 中还提供 callbackify 方法,用于将 async 函数转换为 Error First 风格的函数。

下面通过 callbackify 将 promise 化的 fs 还原为 Error First 风格的函数。

const fs = require('fs/promises')
const util = require('util')const readFile = util.callbackify(fs.readFile)
readFile('./2021-11-12.log', { encoding: 'utf-8' }, (error, text) => {if (error) {console.error(error)return}console.log(text)
})

调试与输出

如果有开发过 Node 服务,应该都用过 debug 模块,通过该模块可以在控制台看到更加明晰的调试信息。

const debug = require('debug')
const log = debug('app')const user = { name: 'shenfq' }log('当前用户: %o', user)
46cdde3ba51afdc9fa957e8faa1751b6.png

其实,通过 util.debug 也能实现类似的效果:

const debug = require('debug')
const log = debug('app')const user = { name: 'shenfq' }log('当前用户: %o', user)

只是在启动时,需要将 DEBUG 环境变量替换为 NODE_DEBUG

a203a13c16ab3589db11ba33b08fff44.png

如果你有认真看上面的代码,应该会发现,在 log('当前用户: %o', user) 方法前面的字符串中,有一个 %o 占位符,表示这个地方将会填充一个对象(object)。这与 C 语言或 python 中的,printf 类似。同样,在 util 模块中,直接提供了格式化的方法:util.format

const { format } = require('util')console.log(format('当前用户: %o', {name: 'shenfq', age: 25})
)
16e9a4acfa74ed3e9a8ce9abd49077a5.png

除了 %o 占位符,不同的数据类型应使用不同的占位符。

占位符类型
%s字符串
%d数字(包括整数和浮点数)
%i整数
%f浮点数
%jJSON
%oObject

JavaScript 中的对象是一个很复杂的东西,除了直接使用 util.format 外加 %o 占位符的方式格式化对象,util 中还提供了一个叫做 inspect 方法来进行对象格式化。

const { inspect } = require('util')const user = {age: 25,name: 'shenfq',work: {name: 'coding',seniority: 5}
}console.log(inspect(user))
5e9afdd4324966b600b460c878a67de0.png

这么看 inspect 好像什么都没做,但是 inspect 方法还有第二个参数,用来进行格式化时的一些个性化配置。

  • depth: number:控制显示层级;

  • sorted: boolean|Function: 是否按照key的编码值进行排序;

  • compact: boolean:是否进行单行显示;

当然上面只是一部分配置,更详细的配置可查阅 node 文档,下面我们写几个案例:

所有的属性都换行显示:

inspect(user, {compact: false
})
587987c83050731fe7cc73fdad5ed647.png

只格式化对象第一层的值:

inspect(user, {depth: 0,compact: false
})
f81f7417cddf8280b2b9181a82afca95.png

按照key值的编码倒序输出:

inspect(user, {compact: false,sorted: (a, b) => a < b ? 1 : -1
})
7b582b16784d7746a4c45fde323d0365.png- END -

最近组建了一个湖南人的前端交流群,如果你是湖南人可以加我微信 ruochuan12 私信 湖南 拉你进群。

推荐阅读

1个月,200+人,一起读了4周源码
我历时3年才写了10余篇源码文章,但收获了100w+阅读

老姚浅谈:怎么学JavaScript?

我在阿里招前端,该怎么帮你(可进面试群)

019c16e72c9ebac005c40bc8c53c79d1.gif

················· 若川简介 ·················

你好,我是若川,毕业于江西高校。现在是一名前端开发“工程师”。写有《学习源码整体架构系列》20余篇,在知乎、掘金收获超百万阅读。
从2014年起,每年都会写一篇年度总结,已经写了7篇,点击查看年度总结。
同时,最近组织了源码共读活动,帮助1000+前端人学会看源码。公众号愿景:帮助5年内前端人走向前列。

bfb4333ccaee148e578073ab4675108c.png

识别方二维码加我微信、拉你进源码共读

今日话题

略。分享、收藏、点赞、在看我的文章就是对我最大的支持~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/275175.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java应用集群下的定时任务处理方案(mysql)

今天来说一个Java多机部署下定时任务的处理方案。 需求: 有两台服务器同时部署了同一套代码&#xff0c; 代码中写有spring自带的定时任务&#xff0c;但是每次执行定时任务时只需要一台机器去执行。 当拿到这个需求时我脑子中立马出现了两个简单的解决方案&#xff1a; 利用ip…

概念验证_设置成功的UX概念验证

概念验证用户体验/概念证明/第1部分 (USER EXPERIENCE / PROOF OF CONCEPT / PART 1) This is the first article of a four-part series. Please read Part 2 and Part 3.这是由四个部分组成的系列文章的第一篇。 请阅读 第2 部分 和 第3部分 。 How do today’s top UX desi…

从 vue3 和 vite 源码中,我学到了一行代码统一规范团队包管理器的神器

1. 前言大家好&#xff0c;我是若川。最近组织了源码共读活动&#xff0c;感兴趣的可以加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。已进行四个月了&#xff0c;很多小伙伴表示收获颇丰。想学源码&#xff0c;极力推荐之前我写…

6个高效办公的Excel小技巧,学会让你高效办公

很多人在做Excel表格的时候&#xff0c;会出现下面这种情况&#xff1a;好不容易把内容都输入好了&#xff0c;才发现文字或是数字的排列组合需要重新调整&#xff0c;这个时候头就大了&#xff0c;到底是要一个个复制黏贴&#xff0c;还是要删除后再添加&#xff1f;不管哪种方…

unity 完美像素_像素完美

unity 完美像素从Kidpix到设计系统 (From Kidpix to design systems) Did you ever create stamps in KidPix? Kidpix is bitmap drawing software that’s been around since the nineties, and I remember many happy — more like maddening — hours creating tiny pixela…

整整4个月了,尽全力组织了源码共读活动~

大家好&#xff0c;我是若川。从8月份到现在11月结束了。每周一期&#xff0c;一起读200行左右的源码&#xff0c;撰写辅助文章&#xff0c;截止到现在整整4个月了。由写有《学习源码整体架构系列》20余篇的若川【若川视野公众号号主】倾力组织&#xff0c;召集了各大厂对于源码…

字节内部前端开发手册(完整版)开放下载!

备战2022&#xff0c;准备好了吗&#xff1f;据字节HR部门发布的最新信息&#xff0c;2019年以来字节连续3年扩招&#xff0c;而即将到来的2022年春招前端岗位数不低于3000&#xff0c;虽连年扩招&#xff0c;但是报录比却从2019年的3%下降到今年的1%。BAT等一线大厂同样有类似…

EBS中Java并发程序笔记(1)

在Oracle EBS中的Java并发程序&#xff08;Java Concurrent Program&#xff09;是系统功能中的一个亮点&#xff0c;它的出现使得用户可以在ERP系统中运行自己定义的Java程序。本文为学习笔记&#xff0c;所以不会介绍太多背景知识。 使用Java并发程序的好处&#xff1a; 当遇…

figma设计_5位来自杂乱无章的设计师的Figma技巧

figma设计When starting a design project, a fast pace and multiple design iterations can easily lead to a cluttered mess. Taking the time in the beginning to build good organizational habits will save you time later. You’ll thank your past self when you do…

设计和实现一个 Chrome 插件提升登录效率

大家好&#xff0c;我是若川。最近组织了源码共读活动&#xff0c;感兴趣的可以点此加我微信ruochuan12 进群参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。已进行4个月了&#xff0c;很多小伙伴表示收获颇丰。前言在我们的工作过程中&#xff0c;每当…

qq空间网页设计_网页设计中的负空间

qq空间网页设计重点 (Top highlight)Because screens are limited, web design is also limited. It can be said that in the small box of the screen, each pixel is a piece of real estate.由于屏幕有限&#xff0c;因此网页设计也受到限制。 可以说&#xff0c;在屏幕的小…

时隔一年半,我,一个卑微的前端菜鸡,又来写面经了

大家好&#xff0c;我是若川。最近组织了源码共读活动&#xff0c;感兴趣的可以点此加我微信ruochuan12 进群参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。已进行4个月了&#xff0c;很多小伙伴表示收获颇丰。作者&#xff1a;刮涂层_赢大奖原文地址…

用户体验与可用性测试_可用性作为用户体验的原则

用户体验与可用性测试Every UX Designer has his views and best practices. We all have a guide book created through time and experience. I want to share mine with you.每个UX设计器都有他的观点和最佳实践。 我们都有一本通过时间和经验编写的指南。 我想和你分享我的…

Jenkins插件之Deploy

deploy插件&#xff1a; Deploy Plugindeploy插件支持将War/Jar部署到远程的应用服务器上&#xff0c;例如Tomcat,JBoss,Glassfish。正在寻找或开发.NET web 应用的自动发布插件。如何回滚或重新部署先前的build&#xff1a;0&#xff09; 需要被deploy的job的结果要存档&#…

受美国法律保护美国妞_为什么美国法律有效地要求所有软件设计都要响应

受美国法律保护美国妞Smashing Magazine defines “responsive design” as an approach where design responds to the user’s behavior and environment based on screen size, platform, and orientation. In responsive design, a breakpoint is the “point” at which a…

源码群友问:你这么多项目是怎么进行技术选型的?

大家好&#xff0c;我是若川。最近组织了源码共读活动&#xff0c;感兴趣的可以点此加我微信ruochuan12 进群参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。已进行4个月了&#xff0c;很多小伙伴表示收获颇丰。源码群有群友提问我是怎么找到那么多npm…

iOS开发之打包上传报错: ERROR ITMS-90087/ERROR ITMS-90125

制作好的framework在打包上传至AppStore如果出现以下错误&#xff0c;则说明这个SDK里面包含了x86_64, i386 架构&#xff0c;当然这个AppStore是不允许的&#xff0c;所以会在上传的时候报错&#xff0c;解决办法就是要这个SDK剔除掉x86_64, i386这两个架构 解决办法&#xff…

ios 动画设计_动画和讲故事在设计中的力量

ios 动画设计As human beings, we’ve always been fond of storytelling. Just think of campfire stories, Santa Claus, or that thrilling book you just finished. Here’s how you can use the power of storytelling to make your designs better.作为人类&#xff0c;我…

poj 2696 A Mysterious Function

A Mysterious FunctionTime Limit: 1000MS Memory Limit: 65536KTotal Submissions: 3517 Accepted: 2398Description For any integers p and q with q > 0, define p mod q to be the integer r with 0 < r < q −1 such that p−r is divisible by q. For example,…

面试官:能不能手写一个 Promise?

大家好&#xff0c;我是若川。最近组织了源码共读活动&#xff0c;感兴趣的可以点此加我微信ruochuan12 进群参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。已进行4个月了&#xff0c;很多小伙伴表示收获颇丰。以下问题你是不是在哪里听过&#xff1f…