Nodejs14⼤版本中新增特性总结
今⽇⽂章由 “Node.js技术栈@五⽉君” 授权分享,正⽂从下⾯开始~
Node.js 是⼀个基于 Chrome V8 引擎 的 JavaScript 运⾏时。在 2020 年 10 ⽉ 27 ⽇ Node.js v14.15.0 LTS 版已发布,即长期⽀持版本,其中包含了很多很棒的新功能,以下内容也是基于笔者在⽇常 Node.js ⼯作和学习中所总结的,可能不全,同时也欢迎补充,有些功能之前也曾单独写过⽂章来介绍,接下让我们⼀起看看都有哪些新的变化?
Optional Chaining(可选链)
如果我们使⽤ JavaScript 不管是⽤在前端或者 Node.js 服务端都会出现如下情况,因为我们有时是不确定 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)
}
现在我们有⼀种优雅的写法 "可选链操作符",不必明确的验证链中的每个引⽤是否有效,以符号 "?." 表⽰,在引⽤为 null 或 undefined 时不会报错,会发⽣短路返回 undefined。
user.address?.city
user.address?.city?.length
// 结合 ?.[] 的⽅式访问相当于 user.address['city']
user.address?.['city']
// 结合 delete 语句使⽤,仅在 user.address.city 存在才删除
delete user.address?.city
Nullish Coalescing(空值合并)
逻辑或操作符(||)会在左侧为假值时返回右侧的操作符,例如我们传⼊⼀个属性为 enabled:0 我们期望输出左侧的值,则是不⾏的。
function Component(props) {
const enable = abled || true; // true
}
Component({ enabled: 0 })
现在我们可以使⽤ **空值合并操作符(??)**来实现,仅当左侧为 undefined 或 null 时才返回右侧的值。
function Component(props) {
const enable = abled ?? true; // 0
}
Component({ enabled: 0 })
Intl.DisplayNames(国际化显⽰名称)
对于国际化应⽤需要⽤到的语⾔、区域、货币、脚本的名称,现在 JavaScript 开发者可以使⽤ Intl.DisplayNames API 直接访问这些翻译,使应⽤程序更轻松的显⽰本地化名称。
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(区域)
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
上述实例⽤到的国家代号和 code 都可从参考地址获取。
Intl.DateTimeFormat(国际化处理⽇期时间格式)
Intl.DateTimeFormat API ⽤来处理特定语⾔环境的⽇期格式。
// 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 中国标准时间下午9:02:29.315
new Intl.DateTimeFormat('zh-CN', {
year: '2-digit',
month: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
fractionalSecondDigits: 3,
timeZoneName: 'long'
}).format(date)
参考:javascript的特性
String.prototype.matchAll (throws on non-global regex)
matchAll() 返回⼀个包含所有匹配正则表达式的结果,返回值为⼀个不可重⽤(不可重⽤意思为读取完之后需要再次获取)的迭代器。
matchAll() ⽅法在 Node.js v12.4.0 以上版本已⽀持,该⽅法有个限制,如果设置的正则表达式没有包含全局模式 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);
}
参考:
Async Local Storage(异步本地存储)
Node.js Async Hooks 模块提供了 API ⽤来追踪 Node.js 程序中异步资源的声明周期,在最新的 v14.x LTS 版本中新增加了⼀个AsyncLocalStorage 类可以⽅便实现上下⽂本地存储,在异步调⽤之间共享
数据,对于实现⽇志链路追踪场景很有⽤。
下⾯是⼀个 HTTP 请求的简单⽰例,模拟了异步处理,并且在⽇志输出时去追踪存储的 id。
const { AsyncLocalStorage } = require('async_hooks');
const asyncLocalStorage = new AsyncLocalStorage();
function logWithId(msg) {
const id = Store();
console.log(`${id !== undefined ? id : '-'}:`, msg);
}
let idSeq = 0;
asyncLocalStorage.run(idSeq++, () => {
logWithId('start');
setImmediate(() => {
logWithId('');
setTimeout(() => {
logWithId('finish');
}, 2000)
});
});
}).listen(8080);
下⾯是运⾏结果,我在第⼀次调⽤之后直接调⽤了第⼆次,可以看到我们存储的 id 信息与我们的⽇志⼀起成功的打印了出来。
image.png
便利性的同时也会牺牲⼀些性能上的代价。
ES Modules ⽀持
ES Modules 的⽀持总体上来说是个好事,进⼀步的规范了 Node.js 与浏览器的模块⽣态,使之进⼀步趋同,同时避免了进⼀步的分裂。在当前 Node.js v14.x LTS 版本中已移除试验性⽀持,现在使⽤⽆需使⽤标志了,它使⽤ import、export 关键字,两种使⽤⽅式:
使⽤ .mjs 扩展名
// caculator.mjs
export function add (a, b) {
return a + b;
};
// index.mjs
import { add } from './caculator.js';
console.log(add(4, 2)); // 6
告诉 Node.js 将 JavaScript 代码视为 ES Modules
默认情况下 Node.js 将 JavaScript 代码视为 CommonJS 规范,所以我们要在上⾯使⽤扩展名为 .mjs 的⽅式来声明,除此之外我们还可以在 package.json ⽂件中 设置 type 字段为 module 或在运⾏ node 时加上标志 --input-type=module 告诉 Node.js 将 JavaScript 代码视为 ES Modules。
// package.json
{
"name": "esm-project",
"type": "module",
...
}
前端的同学可能会对以上使⽤ ES Modules 的⽅式很熟悉。
Top-Level Await(顶级 await ⽀持)
顶级 await ⽀持在异步函数之外使⽤ await 关键字,在 Node.js v14.x LTS 版本中已去掉试验性⽀持,现在使⽤也不再需要设置标志。
import fetch from 'node-fetch';
const res = await fetch(url)
也可以像调⽤函数⼀样动态的导⼊模块。
const myModule = await import('./my-module.js');
对于异步资源,之前我们必须在 async 函数内才可使⽤ await,这对⼀些在⽂件顶部需要实例化的资源可能会不 好操作,现在有了顶级await 我们可以⽅便的在⽂件顶部对这些异步资源做⼀些初始化操作。
Diagnostic report(诊断报告)
Diagnostic report 是 Node.js v14.x LTS 提供的⼀个稳定功能,在某些情况下会⽣成⼀个 JSON 格式的诊断报告,可⽤于开发、测试、⽣产环境。报告会提供有价值的信息,包括:JavaScript 和本机堆栈信息、堆统计信息、平台信息、资源使⽤情况等,帮助⽤户快速追踪问题。
const total = [];
setInterval(function() {
total.push(new Array(20 * 1024 * 1024)); // ⼤内存占⽤,不会被释放
}, 1000)
最终⽣成的 JSON 报告被 report-toolkit ⼯具诊断的结果可能是下⾯这样的。
Stream
新版本中包含了对 Stream 的⼀些更改,旨在提⾼ Stream API 的⼀致性,以消除歧义并简化 Node.js 核⼼各个部分的⾏为,例如:http.OutgoingMessage 与 stream.Writable 类似
net.Socket 的⾏为与 stream.Duplex 完全相同
⼀个显著的变化 autoDestroy 的默认值为 true,使流在结束之后始终调⽤ _destroy
参考:
使⽤异步迭代器
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论