前言
🤡我们知道JS相对于其他编程语言是一门相对来讲比较精简的语言,这种精简给我们编程带来了许多的便利,但是在服务端开发中,这中精简有的时候并不是优点,我们在做一些操作的时候会非常的受限,所以Node为了弥补这个问题就有了utils工具模块,接下来我们就学习一下几个常用的utils模块的使用。
一.util.callbackify
🤗这个方法的作用是将使用async
修饰的函数转为回调错误优先的方式,我们首先来看一个例子。
js
const util = require("util")
async function foo () {
return "HelloWorld"
}
const callbackFunction = util.callbackify(foo)
callbackFunction((err, data) => {
if (err) return
console.log(data)
})
在这个函数的结果中就会输出HelloWorld
,那么很多小伙伴就会有问题了,是不是使用这个方法,被async
修饰的函数必须有返回值?
🤡callbackify
的使用方式是这样的,无论async
修饰的函数有没有返回值,都能够被转为回调错误优先的方式,如果发生错误就会执行error
的分支,如果没有错误就是执行正确的data
分支,只不过data
分支的结果取决于async
函数返回的返回值
js
const util = require('util');
async function foo() {
// 此处没有返回值
console.log('Hello, World!');
}
const callbackFunction = util.callbackify(foo);
callbackFunction((err, data) => {
if (err) {
console.error(err);
return;
}
console.log('依然会打印成功');
});
🫥我们在async
中经常会有await
操作,那么await
操作会对这个函数有什么影响吗?纸上得来终觉浅,绝知此事要躬行,这是我一直秉承的态度。
js
const util = require("util")
async function foo () {
await delay(2000)
return "HelloWorld"
}
// 转为callback
const callback = util.callbackify(foo)
callback((err, data) => {
if (err) {
console.log(err)
return
}
console.log(data)
})
// 模拟异步delay
function delay (ms) {
return new Promise((resolve) => setTimeout(() => {
console.log("TEST")
resolve()
}, ms))
}
接下来我们看下输出的结果:结果显而易见,完全没有任何问题。
我们将成功的状态如果放在输出TEST
之前哪?因为直接输出是同步任务会优先执行,异步任务会等同步执行完之后再执行,所以结果依然没有任何改变。
js
function delay (ms) {
return new Promise((resolve) => setTimeout(() => {
resolve()
console.log("TEST")
}, ms))
}
二.util.promisify(original)
😎有了上边的使用经验,这个方法,我们也就可以直接使用了,使用方法是一样的,代码demo如下:
js
// 引入 Node.js 内置模块 util 和 fs
import util from 'util'
import fs from 'fs'
// 将 fs.readFile 方法转换为返回 Promise 的函数
const fsRead = util.promisify(fs.readFile)
// 使用 Promise 的方式读取文件内容并输出
fsRead('./package.json').then((data) => {
console.log(data.toString())
})
三.util.inherits
👹util.inherits(constructor, superConstructor)
这个方法的作用实现对象间原型继承的函数。原型继承的相关知识我们这里也不做赘述,我们直接来看下这个方法如何使用,这个方法使用起来非常的简单。
js
const util = require('util')
function Father () {
this.name = 'zzz'
this.base = 1991
this.sayHello = function () {
console.log('Hello ' + this.name)
}
}
Father.prototype.showName = function () {
console.log(this.name)
}
function Son () {
this.name = 'sub'
}
util.inherits(Son, Father)
var objBase = new Father()
objBase.showName()
objBase.sayHello()
console.log(objBase)
var objSub = new Son()
objSub.showName()
console.log(objSub)
执行结果如下:
我们可以看到我们并没有去使用父类的sayHello
的方法,那么我们来试一下看下结果:报错!那么原因是什么?
js
var objSub = new Son()
objSub.showName()
obj.sayHello()
console.log(objSub)
😎真相时刻:
inherits这个方法实现的继承,只能够继承原型链上边的函数,在函数体内部的是无法继承的。
四.util.inspect(object, [options])
🫥inspect
方法是将对象抓换成字符串,听到这个你也许会有疑问我用JSON.stringfy
不就可以了吗?
是的,在我们平时将对象转换为字符串经常使用的方法就是JSON.stringfy
比如这样。
js
const obj = {
name: "zpj",
proList: [
{ name: "aaa", age: 12 },
{ name: "bbb", age: 13 },
{ name: "ccc", age: 14 }
]
}
console.log(JSON.stringify(obj))
🤡这种对象比较简单,但是如果是一个及其复杂的对象呢?比如这样
js
const testObj = {
a: 1,
b: {
c: 2,
d: [3, 4, 5],
e: () => {
console.log(6)
}
},
f: '7',
g: [{ 8: [{ 9: 10 }] }],
h () {
console.log(11)
}
}
console.log(JSON.stringify(testObj))
这种情况下就无能为力了,我们可以看到是打印不出来的,那么在服务端开发的时候该怎么办?我该ru'heruhe 解决这种问题?解决这种问题Node也提供了对应的方法。我们使用inspect
方法来进行解析。
js
const util = require('util')
const testObj = {
a: 1,
b: {
c: 2,
d: [3, 4, 5],
e: () => {
console.log(6)
}
},
f: '7',
g: [{ 8: [{ 9: 10 }] }],
h () {
console.log(11)
}
}
console.log(util.inspect(testObj, { depth: Math.Infinity }))
当然实际开发中可以使用 javascript-stringify 这个库,来实现更佳完整友好的转换。
五.判断数据类型
🤗需要注意的是在Node中这些方法现在已经不建议使用了,但是我们可以简单的看下。
js
import util from 'util'
// 判断数据类型
console.log(util.isArray([])) // true
console.log(util.isRegExp(/some regexp/)) // true
console.log(util.isDate(new Date())) // true
console.log(util.isPrimitive(null)) // true
console.log(util.isPrimitive(1)) // true
六.总结
🥱在Node中我们有的时候会有很多的操作需求,但是仅仅使用JS中提供的方法我们你很做到,所以Node就提供了对应的工具类来补充这部分缺陷,常见的工具方法有,异步转回调,回调转异步,判断类型的方法,对象转字符串的方法等等~