溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何理解node.js中Util模塊作用

發(fā)布時間:2021-11-25 13:15:15 來源:億速云 閱讀:235 作者:柒染 欄目:開發(fā)技術(shù)

這篇文章給大家介紹如何理解node.js中Util模塊作用,內(nèi)容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

    從類型判斷說起

    在 JavaScript 中,進行變量的類型校驗是一個非常令人頭疼的事,如果只是簡單的使用 typeof 會到各種各樣的問題。

    舉幾個簡單的:

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

    后來,大家發(fā)現(xiàn)可以使用 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 中,內(nèi)部其實是有一組用來判斷變量類型的 api 的。而且功能異常豐富,除了基礎(chǔ)類型的判斷,還支持判斷 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 中,對象、數(shù)組等變量在判斷相等的過程中,如果用 === 通常只會判斷這兩個變量是否指向同一內(nèi)存地址。如果想判斷對象的鍵對應(yīng)的所有值是否相等,需要對兩個對象進行遍歷。在 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

    該方法同樣可以用來判斷數(shù)組,是否嚴格相等:

    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

    早期的 Node API 都是 Error First 風格的,也就是所有的異步函數(shù)都會接受一個回調(diào)函數(shù),該回調(diào)的一個參數(shù)為 error 對象,如果正常返回 error 對象為 null,后面的參數(shù)為成功響應(yīng)的結(jié)果。

    // 下面是一個讀取文件的示例
    const fs = require('fs')
    fs.readFile('nginx.log', (error, data) => {
      if (error) {
        // 讀取文件失敗
        console.error(error)
        return
      }
      // 讀取文件成功,打印結(jié)果
      console.log(data)
    })

    在 Node 8 發(fā)布的時候,新增了一個 promisify 接口,用于將 Error First 風格的 API 轉(zhuǎn)為 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))

    不過,后來也有很多人覺得這些原生 API 支持 Promise 的方式太過繁瑣,每個 API 都需要單獨的包裝一層 promisify 方法。在 Node 10 發(fā)布的時候,原生模塊都新增了一個 .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))

    注意: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))

    除了將 Error First 風格的 API 轉(zhuǎn)為 Promise API,util 中還提供 callbackify 方法,用于將 async 函數(shù)轉(zhuǎn)換為 Error First 風格的函數(shù)。

    下面通過 callbackify 將 promise 化的 fs 還原為 Error First 風格的函數(shù)。

    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)
    })

    調(diào)試與輸出

    如果有開發(fā)過 Node 服務(wù),應(yīng)該都用過 debug 模塊,通過該模塊可以在控制臺看到更加明晰的調(diào)試信息。

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

    其實,通過 util.debug 也能實現(xiàn)類似的效果:

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

    只是在啟動時,需要將 DEBUG 環(huán)境變量替換為 NODE_DEBUG。

    如果你有認真看上面的代碼,應(yīng)該會發(fā)現(xiàn),在 log('當前用戶: %o', user) 方法前面的字符串中,有一個 %o 占位符,表示這個地方將會填充一個對象(object)。這與 C 語言或 python 中的,printf 類似。同樣,在 util 模塊中,直接提供了格式化的方法:util.format

    const { format } = require('util')
    console.log(
      format('當前用戶: %o', {
        name: 'shenfq', age: 25
      })
    )

    除了 %o 占位符,不同的數(shù)據(jù)類型應(yīng)使用不同的占位符。

    占位符類型
    %s字符串
    %d數(shù)字(包括整數(shù)和浮點數(shù))
    %i整數(shù)
    %f浮點數(shù)
    %jJSON
    %oObject

    JavaScript 中的對象是一個很復(fù)雜的東西,除了直接使用 util.format 外加 %o 占位符的方式格式化對象,util 中還提供了一個叫做 inspect 方法來進行對象格式化。

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

    這么看 inspect 好像什么都沒做,但是 inspect 方法還有第二個參數(shù),用來進行格式化時的一些個性化配置。

    depth: number:控制顯示層級;

    sorted: boolean|Function: 是否按照key的編碼值進行排序;

    compact: boolean:是否進行單行顯示;

    當然上面只是一部分配置,更詳細的配置可查閱 node 文檔,下面我們寫幾個案例:

    所有的屬性都換行顯示:

    inspect(user, {
        compact: false
    })

    只格式化對象第一層的值:

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

    按照key值的編碼倒序輸出:

    inspect(user, {
        compact: false,
      sorted: (a, b) => a < b ? 1 : -1
    })

    關(guān)于如何理解node.js中Util模塊作用就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

    向AI問一下細節(jié)

    免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI