1. Nodejs 14 大版本中新增特性總結(jié)

        共 9721字,需瀏覽 20分鐘

         ·

        2021-03-08 01:44


        今日文章由 “Node.js技術(shù)棧@五月君” 授權(quán)分享,正文從下面開始~


        Node.js 是一個基于 Chrome V8 引擎 的 JavaScript 運(yùn)行時。在 2020 年 10 月 27 日 Node.js v14.15.0 LTS 版已發(fā)布,即長期支持版本,其中包含了很多很棒的新功能,以下內(nèi)容也是基于筆者在日常 Node.js 工作和學(xué)習(xí)中所總結(jié)的,可能不全,同時也歡迎補(bǔ)充,有些功能之前也曾單獨(dú)寫過文章來介紹,接下讓我們一起看看都有哪些新的變化?

        Optional Chaining(可選鏈)

        如果我們使用 JavaScript 不管是用在前端或者 Node.js 服務(wù)端都會出現(xiàn)如下情況,因?yàn)槲覀冇袝r是不確定 user 對象是否存在,又或者 user 對象里面的 address 是否存在,如果不這樣判斷, 可能會得到類似于 Cannot read property 'xxx' of undefined 這樣的類似錯誤。

        const user = {
          name'Tom',
          address: {
            city'ZhengZhou'
          }
        }
        if (user && user.address) {
          console.log(user.address.city)
        }

        現(xiàn)在我們有一種優(yōu)雅的寫法 "可選鏈操作符",不必明確的驗(yàn)證鏈中的每個引用是否有效,以符號 "?." 表示,在引用為 null 或 undefined 時不會報(bào)錯,會發(fā)生短路返回 undefined。

        user.address?.city
        user.address?.city?.length

        // 結(jié)合 ?.[] 的方式訪問相當(dāng)于 user.address['city']
        user.address?.['city']

        // 結(jié)合 delete 語句使用,僅在 user.address.city 存在才刪除
        delete user.address?.city

        參考 https://v8.dev/features/optional-chaining

        Nullish Coalescing(空值合并)

        邏輯或操作符(||)會在左側(cè)為假值時返回右側(cè)的操作符,例如我們傳入一個屬性為 enabled:0 我們期望輸出左側(cè)的值,則是不行的。

        function Component(props{
          const enable = props.enabled || true// true
        }
        Component({ enabled0 })

        現(xiàn)在我們可以使用 **空值合并操作符(??)**來實(shí)現(xiàn),僅當(dāng)左側(cè)為 undefined 或 null 時才返回右側(cè)的值。

        function Component(props{
          const enable = props.enabled ?? true// 0
        }

        Component({ enabled0 })

        參考:https://v8.dev/features/nullish-coalescing

        Intl.DisplayNames(國際化顯示名稱)

        對于國際化應(yīng)用需要用到的語言、區(qū)域、貨幣、腳本的名稱,現(xiàn)在 JavaScript 開發(fā)者可以使用 Intl.DisplayNames API 直接訪問這些翻譯,使應(yīng)用程序更輕松的顯示本地化名稱。

        Language(語言)

        let longLanguageNames = new Intl.DisplayNames(['zh-CN'], { type'language' });
        longLanguageNames.of('en-US'); // 美國英語
        longLanguageNames.of('zh-CN'); // 中文(中國)

        longLanguageNames = new Intl.DisplayNames(['en'], { type'language' });
        longLanguageNames.of('en-US'); // American English
        longLanguageNames.of('zh-CN'); // Chinese (China)

        Region(區(qū)域)

        let regionNames = new Intl.DisplayNames(['zh-CN'], {type'region'});
        regionNames.of('US'); // 美國
        regionNames.of('419'); // 拉丁美洲

        regionNames = new Intl.DisplayNames(['en'], {type'region'});
        regionNames.of('US'); // United States
        regionNames.of('419'); // Latin America

        Currency(貨幣)

        let currencyNames = new Intl.DisplayNames(['zh-CN'], {type'currency'});
        currencyNames.of('CNY'); // 人民幣
        currencyNames.of('USD'); // 美元

        currencyNames = new Intl.DisplayNames(['en'], {type'currency'});
        currencyNames.of('CNY'); // Chinese Yuan
        currencyNames.of('USD'); // US Dollar

        Script(腳本)

        let scriptNames = new Intl.DisplayNames(['zh-CN'], {type'script'});
        scriptNames.of('Hans'); // 簡體
        scriptNames.of('Latn'); // 拉丁文

        scriptNames = new Intl.DisplayNames(['en'], {type'script'});
        scriptNames.of('Hans'); // Simplified
        scriptNames.of('Latn'); // Latin

        參考:https://v8.dev/features/intl-displaynames

        上述實(shí)例用到的國家代號和 code 都可從參考地址獲取。

        Intl.DateTimeFormat(國際化處理日期時間格式)

        Intl.DateTimeFormat API 用來處理特定語言環(huán)境的日期格式。

        const date = new Date();

        // Sunday, January 10, 2021 at 9:02:29 PM GMT+8
        new Intl.DateTimeFormat('en-US', { dateStyle'full'timeStyle'long'}).format(date)

        // 21/1/10 中國標(biāo)準(zhǔn)時間 下午9:02:29.315
        new Intl.DateTimeFormat('zh-CN', {
          year'2-digit',
          month'numeric',
          day'numeric',
          hour'numeric',
          minute'numeric',
          second'numeric',
          fractionalSecondDigits3,
          timeZoneName'long'
        }).format(date)

        參考: 

        https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat

        String.prototype.matchAll (throws on non-global regex)

        matchAll() 返回一個包含所有匹配正則表達(dá)式的結(jié)果,返回值為一個不可重用(不可重用意思為讀取完之后需要再次獲?。┑牡?。

        matchAll() 方法在 Node.js v12.4.0 以上版本已支持,該方法有個限制,如果設(shè)置的正則表達(dá)式?jīng)]有包含全局模式 g ,在 Node.js v14.5.0 之后的版本如果沒有提供會拋出一個 TypeError 異常。

        // const regexp = RegExp('foo[a-z]*','g'); // 正確
        const regexp = RegExp('foo[a-z]*'); // 錯誤,沒有加全局模式
        const str = 'table football, foosball, fo';
        const matches = str.matchAll(regexp); // TypeError: String.prototype.matchAll called with a non-global RegExp argument

        for (const item of matches) {
          console.log(item);
        }

        參考:

        https://node.green/#ES2020-features-String-prototype-matchAll-throws-on-non-global-regex

        Async Local Storage(異步本地存儲)

        Node.js Async Hooks 模塊提供了 API 用來追蹤 Node.js 程序中異步資源的聲明周期,在最新的 v14.x LTS 版本中新增加了一個 AsyncLocalStorage 類可以方便實(shí)現(xiàn)上下文本地存儲,在異步調(diào)用之間共享數(shù)據(jù),對于實(shí)現(xiàn)日志鏈路追蹤場景很有用。

        下面是一個 HTTP 請求的簡單示例,模擬了異步處理,并且在日志輸出時去追蹤存儲的 id。

        const http = require('http');
        const { AsyncLocalStorage } = require('async_hooks');
        const asyncLocalStorage = new AsyncLocalStorage();
        function logWithId(msg{
          const id = asyncLocalStorage.getStore();
          console.log(`${id !== undefined ? id : '-'}:`, msg);
        }
        let idSeq = 0;
        http.createServer((req, res) => {
          asyncLocalStorage.run(idSeq++, () => {
            logWithId('start');
            setImmediate(() => {
              logWithId('processing...');
              setTimeout(() => {
                logWithId('finish');
                res.end();
              }, 2000)
            });
          });
        }).listen(8080);

        下面是運(yùn)行結(jié)果,我在第一次調(diào)用之后直接調(diào)用了第二次,可以看到我們存儲的 id 信息與我們的日志一起成功的打印了出來。

        image.png

        便利性的同時也會犧牲一些性能上的代價。

        ES Modules 支持

        ES Modules 的支持總體上來說是個好事,進(jìn)一步的規(guī)范了 Node.js 與瀏覽器的模塊生態(tài),使之進(jìn)一步趨同,同時避免了進(jìn)一步的分裂。

        在當(dāng)前 Node.js v14.x LTS 版本中已移除試驗(yàn)性支持,現(xiàn)在使用無需使用標(biāo)志了,它使用 import、export 關(guān)鍵字,兩種使用方式:

        使用 .mjs 擴(kuò)展名

        // caculator.mjs
        export function add (a, b{
          return a + b;
        };

        // index.mjs
        import { add } from './caculator.js';

        console.log(add(42)); // 6

        告訴 Node.js 將 JavaScript 代碼視為 ES Modules

        默認(rèn)情況下 Node.js 將 JavaScript 代碼視為 CommonJS 規(guī)范,所以我們要在上面使用擴(kuò)展名為 .mjs 的方式來聲明,除此之外我們還可以在 package.json 文件中 設(shè)置 type 字段為 module 或在運(yùn)行 node 時加上標(biāo)志 --input-type=module 告訴 Node.js 將 JavaScript 代碼視為 ES Modules。

        // package.json
        {
          "name""esm-project",
          "type""module",
          ...
        }

        前端的同學(xué)可能會對以上使用 ES Modules 的方式很熟悉。

        Top-Level Await(頂級 await 支持)

        頂級 await 支持在異步函數(shù)之外使用 await 關(guān)鍵字,在 Node.js v14.x LTS 版本中已去掉試驗(yàn)性支持,現(xiàn)在使用也不再需要設(shè)置標(biāo)志。

        import fetch from 'node-fetch';
        const res = await fetch(url)

        也可以像調(diào)用函數(shù)一樣動態(tài)的導(dǎo)入模塊。

        const myModule = await import('./my-module.js');

        對于異步資源,之前我們必須在 async 函數(shù)內(nèi)才可使用 await,這對一些在文件頂部需要實(shí)例化的資源可能會不 好操作,現(xiàn)在有了頂級 await 我們可以方便的在文件頂部對這些異步資源做一些初始化操作。

        Diagnostic report(診斷報(bào)告)

        Diagnostic report 是 Node.js v14.x LTS 提供的一個穩(wěn)定功能,在某些情況下會生成一個 JSON 格式的診斷報(bào)告,可用于開發(fā)、測試、生產(chǎn)環(huán)境。報(bào)告會提供有價值的信息,包括:JavaScript 和本機(jī)堆棧信息、堆統(tǒng)計(jì)信息、平臺信息、資源使用情況等,幫助用戶快速追蹤問題。

        https://github.com/IBM/report-toolkit 是 IBM 開發(fā)的一個款工具,用于簡化報(bào)告工具的使用,如下是一個簡單 Demo 它會造成服務(wù)的內(nèi)存泄漏。

        const total = [];
        setInterval(function({
          total.push(new Array(20 * 1024 * 1024)); // 大內(nèi)存占用,不會被釋放
        }, 1000)

        最終生成的 JSON 報(bào)告被 report-toolkit 工具診斷的結(jié)果可能是下面這樣的。


        Stream

        新版本中包含了對 Stream 的一些更改,旨在提高 Stream API 的一致性,以消除歧義并簡化 Node.js 核心各個部分的行為,例如:

        • http.OutgoingMessage 與 stream.Writable 類似
        • net.Socket 的行為與 stream.Duplex 完全相同
        • 一個顯著的變化 autoDestroy 的默認(rèn)值為 true,使流在結(jié)束之后始終調(diào)用 _destroy

        參考:

        https://nodejs.medium.com/node-js-version-14-available-now-8170d384567e

        使用異步迭代器

        使用異步迭代器我們可以對 Node.js 中的事件、Stream 亦或者 MongoDB 返回?cái)?shù)據(jù)遍歷,這是一件很有意思的事情,盡管它不是 Node.js v14.x 中新提出的功能,例如 event.on 是在 Node.js v12.16.0 才支持的,這些目前看到的介紹還不太多,因此我想在這里做下簡單介紹。

        在 Events 中使用

        Node.js v12.16.0 中新增了 events.on(emitter, eventName) 方法,返回一個迭代 eventName 事件的異步迭代器,例如啟動一個 Node.js 服務(wù)可以如下這樣寫,想知道它的原理的可以看筆者下面提到的相關(guān)文章介紹。

        import { createServer as server } from 'http';
        import { on } from 'events';
        const ee = on(server().listen(3000), 'request');
        for await (const [{ url }, res] of ee)
          if (url === '/hello')
            res.end('Hello Node.js!');
          else
            res.end('OK!');

        在 Stream 中使用

        以往我們可以通過 on('data') 以事件監(jiān)聽的方式讀取數(shù)據(jù),通過異步迭代器可以一種更簡單的方式實(shí)現(xiàn)。

        async function readText(readable{
          let data = '';
          for await (const chunk of readable) {
            data += chunk;
          }
          return data;
        }

        目前在 JavaScript 中還沒有被默認(rèn)設(shè)定 [Symbol.asyncIterator] 屬性的內(nèi)建對象,在 Node.js 的一些模塊 Events、Stream 中是可使用的,另外你還可以用它來遍歷 MongoDB 的返回結(jié)果。

        ??愛心三連擊

        1.看到這里了就點(diǎn)個在看支持下吧,你的點(diǎn)贊在看是我創(chuàng)作的動力。

        2.關(guān)注公眾號程序員成長指北,回復(fù)「1」加入高級前端交流群!「在這里有好多 前端 開發(fā)者,會討論 前端 Node 知識,互相學(xué)習(xí)」!

        3.也可添加微信【ikoala520】,一起成長。

        “在看轉(zhuǎn)發(fā)”是最大的支


        點(diǎn)贊和在看就是最大的支持??

        瀏覽 67
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報(bào)
          
          

            1. 中文字幕乱码亚洲无线三区 | 日韩精品成人一区二区在线观看 | 国产ts一区二区三区 | freexxxxhdvideo中国 | 九七成人电影 |