<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                &emsp;&emsp;在 Node.js 中,提供了[console](https://nodejs.org/dist/latest-v18.x/docs/api/console.html)模塊,這是一個簡單的調試控制臺,其功能類似于瀏覽器提供的 JavaScript 控制臺。 &emsp;&emsp;本系列所有的示例源碼都已上傳至Github,[點擊此處](https://github.com/pwstrick/node)獲取。? ## 一、原理 &emsp;&emsp;與瀏覽器一樣,Node.js 也提供了一個全局變量 console(實例化 Console 類),可調用 log()、error() 等方法。 **1)同步還是異步** &emsp;&emsp;console 的方法既不像瀏覽器中那樣始終同步,也不像 Node.js 中的流那樣始終異步。 &emsp;&emsp;是否為同步取決于鏈接的是什么流以及操作系統是 Windows 還是 POSIX: * 文件:在 Windows 和 POSIX 中都是同步。 * TTY(終端):在 Windows 上是異步,在 POSIX 上是同步。 * 管道和套接字:在 Windows 上是同步,在 POSIX 上是異步。 &emsp;&emsp;可移植操作系統接口(Portable Operating System Interface,縮寫為POSIX)是 IEEE 為要在各種 UNIX 操作系統上運行軟件,而定義API的一系列互相關聯的標準的總稱。 &emsp;&emsp;console 的這些行為部分是出于歷史原因,因為一旦將它們更改,那么會導致向后不兼容(即不兼容舊版本)。 &emsp;&emsp;注意,同步寫入會阻塞事件循環,直至寫入完成。 &emsp;&emsp;在輸出到文件的情況下,這可能幾乎是瞬時的。 &emsp;&emsp;但在系統負載高、接收端未讀取管道或終端或文件系統速度較慢的情況下,事件循環可能經常被阻塞足夠長,足以對性能產生嚴重的負面影響。 **2)log() 和 error()** &emsp;&emsp;在[src/lib/internal/console/constructor.js](https://github.com/nodejs/node/blob/master/lib/internal/console/constructor.js)中,存儲著 console.log() 和 console.error() 兩個方法的源碼。 &emsp;&emsp;下面是刪減過的源碼,可以看到在輸出之前會自動加換行符,并且 log() 和 error() 使用的輸出方法還不同。 ~~~ function(streamSymbol, string) { const groupIndent = this[kGroupIndent]; const useStdout = streamSymbol === kUseStdout; // 若是普通輸出,則用 process.stdout 輸出,若是錯誤,則用 process.stderr 輸出 const stream = useStdout ? this._stdout : this._stderr; const errorHandler = useStdout ? this._stdoutErrorHandler : this._stderrErrorHandler; if (groupIndent.length !== 0) { if (StringPrototypeIncludes(string, "\n")) { string = StringPrototypeReplace(string, /\n/g, `\n${groupIndent}`); } string = groupIndent + string; } // 末尾加換行 string += "\n"; try { // 控制臺輸出 stream.write(string, errorHandler); } catch (e) { // Console is a debugging utility, so it swallowing errors is not // desirable even in edge cases such as low stack space. if (isStackOverflowError(e)) throw e; // Sorry, there's no proper way to pass along the error here. } finally { stream.removeListener("error", noop); } } ~~~ &emsp;&emsp;若是 log() 輸出,則用 process.stdout.write() 方法;若是 error() 輸出,則用 process.stderr.write() 方法。 &emsp;&emsp;process.stdout 返回的是一個流,配合 util 模塊的[inspect()](https://nodejs.org/dist/latest-v18.x/docs/api/util.html#utilinspectobject-options)方法,可將對象解析成字符串,并在控制臺著色,如下所示。 ~~~ const util = require('util'); const str = util.inspect({ name: "strick" }, { colors: true }); process.stdout.write(str +'\n'); ~~~ :-: ![](https://img.kancloud.cn/61/0e/610e8eb9577b7c6e079a502600d184b9_576x62.png) ## 二、bunyan.js &emsp;&emsp;目前在我們的項目中,使用的日志庫是[bunyan.js](https://github.com/trentm/node-bunyan),這個庫不僅支持終端和 Node.js 環境,還支持瀏覽器環境。 **1)原理** &emsp;&emsp;從 Github 上下載源碼后,可以看到 bin 和 lib 兩個目錄,終端的代碼存于前者,項目中引用的代碼存于后者。 &emsp;&emsp;下面是一個簡單的示例,引入后也不用實例化,可直接調用方法,log.info() 相當于 console.log(),不過前者會自動將對象轉換成字符串。 ~~~ const bunyan = require('bunyan'); const log = bunyan.createLogger({name: "example"}); log.info("strick"); ~~~ &emsp;&emsp;在日志內部,會為每條日志維護一個對象,像上面的 strick 字符串,在內部生成的對象格式如下。 ~~~ { name: 'example', hostname: '192.168.0.101', pid: 94371, level: 30, msg: 'strick', time: 2022-05-11T07:21:51.310Z, v: 0 } ~~~ &emsp;&emsp;下面是日志輸出的核心代碼(已做刪減),其中 s.stream 使用的也是 process.stdout 類。 &emsp;&emsp;fastAndSafeJsonStringify() 函數用于將對象轉換成字符串,它的工作原理會在后文分析。 ~~~ Logger.prototype._emit = function (rec, noemit) { var i; // 將對象轉換成字符串 var str; if (noemit || this.haveNonRawStreams) { str = fastAndSafeJsonStringify(rec) + os.EOL; } if (noemit) return str; var level = rec.level; for (i = 0; i < this.streams.length; i++) { var s = this.streams[i]; if (s.level <= level) { // 輸出原始對象或字符串 s.stream.write(s.raw ? rec : str); } } return str; }; ~~~ &emsp;&emsp;默認運行 node src.js,在控制臺輸出時是沒有著色的,不便于閱讀。 &emsp;&emsp;在本地調試 bunyan 庫時,可以加 node src.js | ../bin/bunyan,執行此命令后,不僅能著色,還會格式化成可讀性更高的字符串,如下所示。 :-: ![](https://img.kancloud.cn/84/0b/840bf3c9057585be0cb586557f3f4919_1820x116.png =800x) &emsp;&emsp;注意,在項目中加載此庫后,命令中就不需要加路徑了,例如 node index.js | bunyan。 **2)fastAndSafeJsonStringify()** &emsp;&emsp;此函數會在 JSON 對象序列化時,處理對象中的循環和 getter 異常,如下所示。 &emsp;&emsp;第一組 try-catch 用于處理[JSON.stringify()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify)的異常,第二組 try-catch 用于處理 JSON.stringify(rec, safeCycles()) 的異常。 &emsp;&emsp;最后會判斷是否安裝了[safe-json-stringify](https://github.com/debitoor/safe-json-stringify)庫,若安裝就用該庫處理,否則就輸出報錯信息。 ~~~ function fastAndSafeJsonStringify(rec) { try { return JSON.stringify(rec); } catch (ex) { try { return JSON.stringify(rec, safeCycles()); } catch (e) { // 安裝了 safe-json-stringify 庫 if (safeJsonStringify) { return safeJsonStringify(rec); } else { var dedupKey = e.stack.split(/\n/g, 3).join("\n"); _warn( "bunyan: ERROR: Exception in " + "`JSON.stringify(rec)`. You can install the " + '"safe-json-stringify" module to have Bunyan fallback ' + "to safer stringification. Record:\n" + _indent(format("%s\n%s", util.inspect(rec), e.stack)), dedupKey ); return format( "(Exception in JSON.stringify(rec): %j. " + "See stderr for details.)", e.message ); } } } } ~~~ &emsp;&emsp;接下來看一個循環引用的例子,如下所示,在調用 JSON.stringify() 方法時會報錯:TypeError: Converting circular structure to JSON。 &emsp;&emsp;一般自己寫的 JSON 對象很少會出現循環引用,但是在一些比較復雜的對象內部有可能會出現。 ~~~ const man = { child: {} } man.child = man; JSON.stringify(man); ~~~ &emsp;&emsp;在 bunyan.js 的內部給出了兩種解決方案,一種是用[Set](http://www.hmoore.net/pwstrick/fe-questions/1094987)數據類型處理,另一種是用數組處理。 &emsp;&emsp;解決思路其實差不多,都是依次將屬性值加到數據結構中,當判斷到已存在時,就返回 \[Circular\],終止其后面屬性的序列化。 ~~~ var safeCycles = typeof (Set) !== 'undefined' ? safeCyclesSet : safeCyclesArray; // Set 方式 function safeCyclesSet() { var seen = new Set(); return function (key, val) { // 若 value 不存在或不是對象類型,則返回該值 if (!val || typeof val !== "object") { return val; } // 若 seen 中包含該值,則返回 [Circular] if (seen.has(val)) { return "[Circular]"; } seen.add(val); return val; }; } // 數組方式 function safeCyclesArray() { var seen = []; return function (key, val) { if (!val || typeof val !== "object") { return val; } if (seen.indexOf(val) !== -1) { return "[Circular]"; } seen.push(val); return val; }; } ~~~ &emsp;&emsp;JSON.stringify() 方法的第二個參數是一個回調,被序列化的值的每個屬性都會經過該函數的處理。 &emsp;&emsp;在調用 safeCyclesSet() 函數后,就能輸出 {"child":"\[Circular\]"}。 ~~~ JSON.stringify(man, safeCyclesSet()); // {"child":"[Circular]"} ~~~ 參考資料: [日志模塊](https://www.nodejs.red/#/nodejs/console) [process對象](https://javascript.ruanyifeng.com/nodejs/process.html) [官網 process](https://nodejs.org/dist/latest-v18.x/docs/api/process.html#a-note-on-process-io)?[console](https://nodejs.org/dist/latest-v18.x/docs/api/console.html) ***** > 原文出處: [博客園-Node.js精進](https://www.cnblogs.com/strick/category/2154090.html) [知乎專欄-前端性能精進](https://www.zhihu.com/column/c_1611672656142725120) 已建立一個微信前端交流群,如要進群,請先加微信號freedom20180706或掃描下面的二維碼,請求中需注明“看云加群”,在通過請求后就會把你拉進來。還搜集整理了一套[面試資料](https://github.com/pwstrick/daily),歡迎瀏覽。 ![](https://box.kancloud.cn/2e1f8ecf9512ecdd2fcaae8250e7d48a_430x430.jpg =200x200) 推薦一款前端監控腳本:[shin-monitor](https://github.com/pwstrick/shin-monitor),不僅能監控前端的錯誤、通信、打印等行為,還能計算各類性能參數,包括 FMP、LCP、FP 等。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看