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

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

          共 9721字,需瀏覽 20分鐘

           ·

          2021-03-08 01:44


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


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

          Optional Chaining(可選鏈)

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

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

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

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

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

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

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

          Nullish Coalescing(空值合并)

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

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

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

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

          Component({ enabled0 })

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

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

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

          Language(語(yǔ)言)

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

          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'); // 美國(guó)
          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'); // 簡(jiǎn)體
          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í)例用到的國(guó)家代號(hào)和 code 都可從參考地址獲取。

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

          Intl.DateTimeFormat API 用來(lái)處理特定語(yǔ)言環(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 中國(guó)標(biāo)準(zhǔn)時(shí)間 下午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() 返回一個(gè)包含所有匹配正則表達(dá)式的結(jié)果,返回值為一個(gè)不可重用(不可重用意思為讀取完之后需要再次獲取)的迭代器。

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

          // const regexp = RegExp('foo[a-z]*','g'); // 正確
          const regexp = RegExp('foo[a-z]*'); // 錯(cuò)誤,沒有加全局模式
          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(異步本地存儲(chǔ))

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

          下面是一個(gè) HTTP 請(qǐng)求的簡(jiǎn)單示例,模擬了異步處理,并且在日志輸出時(shí)去追蹤存儲(chǔ)的 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)用了第二次,可以看到我們存儲(chǔ)的 id 信息與我們的日志一起成功的打印了出來(lái)。

          image.png

          便利性的同時(shí)也會(huì)犧牲一些性能上的代價(jià)。

          ES Modules 支持

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

          在當(dāng)前 Node.js v14.x LTS 版本中已移除試驗(yàn)性支持,現(xiàn)在使用無(wú)需使用標(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 的方式來(lái)聲明,除此之外我們還可以在 package.json 文件中 設(shè)置 type 字段為 module 或在運(yùn)行 node 時(shí)加上標(biāo)志 --input-type=module 告訴 Node.js 將 JavaScript 代碼視為 ES Modules。

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

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

          Top-Level Await(頂級(jí) await 支持)

          頂級(jí) 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ù)一樣動(dòng)態(tài)的導(dǎo)入模塊。

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

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

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

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

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

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

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


          Stream

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

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

          參考:

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

          使用異步迭代器

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

          在 Events 中使用

          Node.js v12.16.0 中新增了 events.on(emitter, eventName) 方法,返回一個(gè)迭代 eventName 事件的異步迭代器,例如啟動(dòng)一個(gè) 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ù),通過異步迭代器可以一種更簡(jiǎn)單的方式實(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)建對(duì)象,在 Node.js 的一些模塊 Events、Stream 中是可使用的,另外你還可以用它來(lái)遍歷 MongoDB 的返回結(jié)果。

          ??愛心三連擊

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

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

          3.也可添加微信【ikoala520】,一起成長(zhǎng)。

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


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

          瀏覽 67
          點(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>
                  想要xx在线 | 99er这里只有精品 | 亚洲蜜乳| 中文无码一区二区三区四区 | 激情婷婷av |