Speaking from the type judgment
In JavaScript, the type verification of variables is a very headache. If you simply use typeof
, you will encounter various problems.
Give a few simple 🌰:
console.log(typeof null) // 'object'
console.log(typeof new Array) // 'object'
console.log(typeof new String) // 'object'
Later, everyone found that the Object.prototype.toString()
method can be used to judge the variable type.
const getTypeString = obj => Object.prototype.toString.call(obj)
getTypeString(null) // '[object Null]'
getTypeString('string') //'[object String]'
getTypeString(new String) //'[object String]'
By toString()
method, we can get a type string, and we can do things on this string.
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, in Node.js, there is actually a set of apis used to determine the type of variables. Moreover, the functions are extremely rich. In addition to the judgment of basic types, it also supports the judgment of Promise objects, Date objects, and various ArrayBuffers.
const types = require('util/types')
types.isDate(new Date) // true
types.isPromise(new Promise(() => {})) // true
types.isArrayBuffer(new ArrayBuffer(16)) // true
Strictly equal
In JavaScript, in the process of judging the equality of variables such as objects and arrays, if ===
is used, it usually only judges whether these two variables point to the same memory address. If you want to determine whether all the values corresponding to the keys of an object are equal, you need to traverse the two objects. In util
, a method is also provided to determine whether two objects are strictly equal: 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
This method can also be used to determine whether an array is strictly equal:
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
Error First & Promise
The early Node APIs are all in the Error First
, that is, all asynchronous functions will accept a callback function. One parameter of the callback is the error object. If the error object is null
, 061931ec2cc57b, the latter parameter is the result of a successful response.
// 下面是一个读取文件的示例
const fs = require('fs')
fs.readFile('nginx.log', (error, data) => {
if (error) {
// 读取文件失败
console.error(error)
return
}
// 读取文件成功,打印结果
console.log(data)
})
When Node 8 was released, a new promisify
interface was added to convert the Error First
style API to the 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))
However, many people later felt that the way these native APIs support Promise was too cumbersome, and each API required a separate layer of the promisify
method. When Node 10 was released, the native module added a .promises
attribute, and all APIs under this attribute were Promise-style.
const fs = require('fs').promises
fs.readFile('./2021-11-11.log', { encoding: 'utf-8' })
.then(text => console.log(text))
.catch(error => console.error(error))
Note that : After Node 14, a promises
API, which is introduced by modifying the package name.
const fs = require('fs/promises')
fs.readFile('./2021-11-11.log', { encoding: 'utf-8' })
.then(text => console.log(text))
.catch(error => console.error(error))
In addition to converting the Error First
style API to the Promise API, util
also provides the callbackify
method to convert the async
function to the Error First
style function.
Next, use callbackify
to fs
to the Error First
style function.
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)
})
Debug and output
If you have developed a Node service, you should have used the debug
module. Through this module, you can see more clear debugging information on the console.
const debug = require('debug')
const log = debug('app')
const user = { name: 'shenfq' }
log('当前用户: %o', user)
In fact, a similar effect can be achieved util.debug
const debug = require('debug')
const log = debug('app')
const user = { name: 'shenfq' }
log('当前用户: %o', user)
Just at startup, you need to DEBUG
environment variable with NODE_DEBUG
.
If you look at the above code carefully, you should find that in the before the 1619331ec2ccc1e log('current user: %o', user) method, there is a
%o
placeholder, indicating that this place will be filled with an object ( object). This is similar to printf
in C language or python. Similarly, in the util
module, the formatting method is directly provided: util.format
.
const { format } = require('util')
console.log(
format('当前用户: %o', {
name: 'shenfq', age: 25
})
)
In addition to the %o
placeholder, different data types should use different placeholders.
Placeholder | type |
---|---|
%s | String |
%d | Numbers (including integers and floating point numbers) |
%i | Integer |
%f | Floating point |
%j | JSON |
%o | Object |
Objects in JavaScript are a very complicated thing. In addition to formatting objects util.format
plus %o
util
also provides a inspect
to format objects.
const { inspect } = require('util')
const user = {
age: 25,
name: 'shenfq',
work: {
name: 'coding',
seniority: 5
}
}
console.log(inspect(user))
Looking at inspect
seems to have done nothing, but the inspect
method also has a second parameter, which is used for some personalized configuration during formatting.
depth: number
: Control the display level;sorted: boolean|Function
: Whether to sort according to the code value of the key;compact: boolean
: Whether to display a single line;
Of course, the above is only a part of the configuration. For more detailed configuration, please refer to the node documentation. Below we write a few cases:
All attributes are displayed in a new line:
inspect(user, {
compact: false
})
Format only the value of the first level of the object:
inspect(user, {
depth: 0,
compact: false
})
Output in reverse order according to the encoding of the key value:
inspect(user, {
compact: false,
sorted: (a, b) => a < b ? 1 : -1
})
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。