<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          你不知道的 Node.js util

          共 4775字,需瀏覽 10分鐘

           ·

          2021-11-17 18:44

          從類(lèi)型判斷說(shuō)起

          在 JavaScript 中,進(jìn)行變量的類(lèi)型校驗(yàn)是一個(gè)非常令人頭疼的事,如果只是簡(jiǎn)單的使用 typeof 會(huì)到各種各樣的問(wèn)題。

          舉幾個(gè)簡(jiǎn)單的??:

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

          后來(lái),大家發(fā)現(xiàn)可以使用 Object.prototype.toString() 方法來(lái)進(jìn)行變量類(lèi)型的判斷。

          const?getTypeString?=?obj?=>?Object.prototype.toString.call(obj)

          getTypeString(null)?//?'[object?Null]'
          getTypeString('string')?//'[object?String]'
          getTypeString(new?String)?//'[object?String]'

          對(duì) toString() 方法進(jìn)行代理,可以得到一個(gè)類(lèi)型字符串,我們就可以在這個(gè)字符串上面搞事情。

          const?getTypeString?=?obj?=>?{
          ??return?Object.prototype.toString.call(obj)
          }
          const?isType?=?type?=>?{
          ??return?obj?=>?{
          ????return?getTypeString(obj)?===?`[object?${type}]`
          ??}
          }

          const?isArray?=?isType('Array')?//?該方法一般通過(guò)?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)部其實(shí)是有一組用來(lái)判斷變量類(lèi)型的 api 的。而且功能異常豐富,除了基礎(chǔ)類(lèi)型的判斷,還支持判斷 Promise 對(duì)象、Date 對(duì)象、各種ArrayBuffer。

          const?types?=?require('util/types')

          types.isDate(new?Date)?//?true
          types.isPromise(new?Promise(()?=>?{}))?//?true
          types.isArrayBuffer(new?ArrayBuffer(16))?//?true

          嚴(yán)格相等

          在 JavaScript 中,對(duì)象、數(shù)組等變量在判斷相等的過(guò)程中,如果用 === 通常只會(huì)判斷這兩個(gè)變量是否指向同一內(nèi)存地址。如果想判斷對(duì)象的鍵對(duì)應(yīng)的所有值是否相等,需要對(duì)兩個(gè)對(duì)象進(jìn)行遍歷。在 util 中,也提供了一個(gè)方法可以用來(lái)判斷兩個(gè)對(duì)象是否嚴(yán)格相等: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

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

          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 風(fēng)格的,也就是所有的異步函數(shù)都會(huì)接受一個(gè)回調(diào)函數(shù),該回調(diào)的一個(gè)參數(shù)為 error 對(duì)象,如果正常返回 error 對(duì)象為 null,后面的參數(shù)為成功響應(yīng)的結(jié)果。

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

          在 Node 8 發(fā)布的時(shí)候,新增了一個(gè) promisify 接口,用于將 Error First 風(fēng)格的 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))

          不過(guò),后來(lái)也有很多人覺(jué)得這些原生 API 支持 Promise 的方式太過(guò)繁瑣,每個(gè) API 都需要單獨(dú)的包裝一層 promisify 方法。在 Node 10 發(fā)布的時(shí)候,原生模塊都新增了一個(gè) .promises 屬性,該屬性下的所有 API 都 Promise 風(fēng)格的。

          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 又新增了一種引入方式,通過(guò)修改包名的方式引入。

          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 風(fēng)格的 API 轉(zhuǎn)為 Promise API,util 中還提供 callbackify 方法,用于將 async 函數(shù)轉(zhuǎn)換為 Error First 風(fēng)格的函數(shù)。

          下面通過(guò) callbackify 將 promise 化的 fs 還原為 Error First 風(fēng)格的函數(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)試與輸出

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

          const?debug?=?require('debug')
          const?log?=?debug('app')

          const?user?=?{?name:?'shenfq'?}

          log('當(dāng)前用戶(hù):?%o',?user)

          其實(shí),通過(guò) util.debug 也能實(shí)現(xiàn)類(lèi)似的效果:

          const?debug?=?require('debug')
          const?log?=?debug('app')

          const?user?=?{?name:?'shenfq'?}

          log('當(dāng)前用戶(hù):?%o',?user)

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

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

          const?{?format?}?=?require('util')

          console.log(
          ??format('當(dāng)前用戶(hù):?%o',?{
          ????name:?'shenfq',?age:?25
          ??})
          )

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

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

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

          const?{?inspect?}?=?require('util')

          const?user?=?{
          ??age:?25,
          ??name:?'shenfq',
          ??work:?{
          ????name:?'coding',
          ????seniority:?5
          ??}
          }

          console.log(inspect(user))

          這么看 inspect 好像什么都沒(méi)做,但是 inspect 方法還有第二個(gè)參數(shù),用來(lái)進(jìn)行格式化時(shí)的一些個(gè)性化配置。

          • depth: number:控制顯示層級(jí);
          • sorted: boolean|Function: 是否按照key的編碼值進(jìn)行排序;
          • compact: boolean:是否進(jìn)行單行顯示;

          當(dāng)然上面只是一部分配置,更詳細(xì)的配置可查閱 node 文檔,下面我們寫(xiě)幾個(gè)案例:

          所有的屬性都換行顯示:

          inspect(user,?{
          ?compact:?false
          })

          只格式化對(duì)象第一層的值:

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

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

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


          瀏覽 44
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  中国 免费XXXX18 | 91caobi在线 | 无码日日爽天天干 | 性做久久久久久免费观看欧美 | 国产精品999999 |