隆重推出 WHATWG URL API,已在 Node.js 8.0 中正式实现!
你好。
我是Mandai,负责Wild 开发团队。
不久前,Node.js 8.0.0 于 2017 年 5 月 30 日发布。
从这个版本开始,捆绑了 npm 5.0.0 版本,并且围绕缓存的代码已被重写,似乎速度更快。
还发布了一条与过去版本进行速度比较的推文,在本例中,安装完成速度似乎是之前版本的 1/5。
随着#npm5即将发布,我想我应该更新这些基准。
这是我正在处理的 npm5 代码,与流行存储库上的[email protected]pic.twitter.com/KWPfbpE46p
— ✨11x 同性恋 Kat✨ (@maybekatz) 2017 年 5 月 19 日
目前V8引擎的版本是5.8版本,但似乎与V8 5.9和V8 6.0兼容,并且未来的版本预计会通过升级版本的V8引擎变得更快。 → Node.js 8.0 发布。 npm 5.0 捆绑包,包含 Node.js API,官方支持 WHATWG URL 解析器等 - Publickey
这次我想看一下 WHATWG URL API,它在 Node.js 8.0 中正式实现。
什么是WG URL API! ?
实际上,WHATWG URL API 从 Node.js 7 系列开始就已经存在,但在 8.0.0 才成为正式版本。
很多人可能已经使用过它,但由于它处于“实验”地位,他们可能对在生产环境中使用它有点犹豫。
该 API 旨在标准化 URL 解析,并作为传统 URL 模块的扩展提供。
const URL = require('url').URL; const BeyondUrl = new URL('http://www.beyondjapan.com/?abc=123&xyz=999#first'); // 结果URL { href: 'http://www.beyondjapan.com/?abc=123&xyz=999#first', 来源: 'http://www.beyondjapan.com', 协议: 'http:', 用户名: '' ,密码:'',主机:'www.beyondjapan.com',主机名:'www.beyondjapan.com',端口:'',路径名:'/',搜索:'?abc=123&xyz=999',searchParams: URLSearchParams { 'abc' => '123', 'xyz' => '999' }, 哈希值: '#first' }
当然你也可以使用URL模块,感觉和以前一样。
const url = require('url'); const BeyondUrl = 'http://www.beyondjapan.com/?abc=123&xyz=999#first'; console.log(url.parse(beyondUrl)); { 协议:'http:',斜杠:true,身份验证:null,主机:'www.beyondjapan.com',端口:null,主机名:'www.beyondjapan.com',哈希:'#first',搜索:' ?abc=123&xyz=999',查询:'abc=123&xyz=999',路径名:'/',路径:'/?abc=123&xyz=999',href:'http://www.beyondjapan.com/? abc=123&xyz=999#第一' }
令人困惑的是,只有对象名称略有不同,但输出对象的内容也略有不同。
在 WHATWG URL API 的响应中,使用键 searchParams 解析并返回查询字符串很方便。
仅此一点就让您想使用它。
URL 对象的行为
从 WHATWG API 返回的 URL 对象也可以访问每个数据。
const u = 'http://www.beyondjapan.com/?abc=123&xyz=999#first'; const URL = require('url').URL; const BeyondUrl = new URL(u); .hostname); // 结果 www.beyondjapan.com
尝试使用不同的主机名。
const u = 'http://www.beyondjapan.com/?abc=123&xyz=999#first'; const URL = require('url').URL; const BeyondUrl = new URL(u); example.com'; console.log(beyondUrl); // 结果 URL { href: 'http://example.com/?abc=123&xyz=999#first', origin: 'http://example.com',协议:'http:',用户名:'',密码:'',主机:'example.com',主机名:'example.com',端口:'',路径名:'/',搜索:'?abc= 123&xyz=999', searchParams: URLSearchParams { 'abc' => '123', 'xyz' => '999' }, 哈希: '#first' }
仅识别并重写主机名,因此如果执行以下操作,则仅更改主机名。
const u = 'http://www.beyondjapan.com/?abc=123&xyz=999#first'; const URL = require('url').URL; const BeyondUrl = new URL(u); example.com:443'; // 尝试添加端口号 console.log(beyondUrl); // 结果 URL { href: 'http://example.com/?abc=123&xyz=999#first', origin: ' http://example.com', 协议: 'http:', // 不变 用户名: '', 密码: '', 主机: 'example.com', 主机名: 'example.com', 端口: ' ', // 不变的路径名: '/', search: '?abc=123&xyz=999', searchParams: URLSearchParams { 'abc' => '123', 'xyz' => '999' }, hash: '#first' }
如果要更改端口号,需要正确更改端口号。
const u = 'http://www.beyondjapan.com/?abc=123&xyz=999#first'; const URL = require('url').URL; const BeyondUrl = 新 URL(u); ; console.log(beyondUrl); // 结果 URL { href: 'http://www.beyondjapan.com:443/?abc=123&xyz=999#first', origin: 'http://www.beyondjapan.com :443', 协议: 'http:', // 不变 用户名: '', 密码: '', 主机: 'www.beyondjapan.com:443', 主机名: 'www.beyondjapan.com', 端口: ' 443 ', 路径名: '/', 搜索: '?abc=123&xyz=999', searchParams: URLSearchParams { 'abc' => '123', 'xyz' => '999' }, 哈希: '#first' }
但更换主机后似乎就不是这样了。
const u = 'http://www.beyondjapan.com/?abc=123&xyz=999#first'; const URL = require('url').URL; const BeyondUrl = new URL(u); example.com:443'; console.log(beyondUrl); // 结果 URL { href: 'http://example.com:443/?abc=123&xyz=999#first', origin: 'http://example .com:443', protocol: 'http:', // 未更改 username: '', 密码: '', host: 'example.com:443', // 已更改 hostname: 'example.com', // 已更改port: '443', // 更改路径名: '/', search: '?abc=123&xyz=999', searchParams: URLSearchParams { 'abc' => '123', 'xyz' => '999 ' }, hash : '#第一的' }
URLSearchParams 类
前面我们研究了 URL 对象的行为,但现在让我们看看从 URL.searchParams 获取的 URLSearchParams 类。
该对象是 Node.js 7 系列中实现的一个类,用于解析查询字符串并提供 getters/setters。
官方文档将其与querystring模块进行了比较,但似乎URLSearchParams类没有querystring模块那么灵活,所以这并不意味着querystring模块是不必要的。
URLSearchParams 类作为 URL 模块中的类提供,因此也可以独立使用。
因此,它是一个强大的类,不仅可以用于分析,还可以用于生成。
const {URLSearchParams} = require('url'); const qs = 'abc=123&xyz=456&aaa=789'; const qsObject = { abc:123, xyz:456, aaa:789 }; , 123], ['xyz', 456], ['aaa', 789], ]; const qsMap = new Map(); qsMap.set('abc', 123); ); qsMap.set('aaa', 789); 函数* qsGenerator(){ 产量 ['abc', 123]; 产量 ['aaa', 789]; new URLSearchParams(qs); // 即使是常规查询字符串格式 const params2 = new URLSearchParams(qsObject); // 即使是常规对象 const params3 = new URLSearchParams(qsIterable); // 即使是迭代器 const params4 = new URLSearchParams (qsMap) ); // 也在 Map 对象中 const params5 = new URLSearchParams(qsGenerator()); // 即使在生成器中 console.log(params2); (params4 ); console.log(params5); // 结果 URLSearchParams { 'abc' => '123', 'xyz' => '456', 'aaa' => '789' } URLSearchParams { 'abc' => '123', 'xyz' => '456', 'aaa' => '789' } URLSearchParams { 'abc' => '123', 'xyz' => '456', 'aaa' => '789' } URLSearchParams { 'abc' => '123', 'xyz' => '456', 'aaa' => '789' } URLSearchParams { 'abc' => '123', 'xyz' => '456', 'aaa' => '789' }
她是一个挑剔的孩子,什么东西都会吃,包括对象、数组、地图对象和生成器。
创建的 URLSearchParams 对象有多种方法。
追加以添加
const {URLSearchParams} = require('url'); const qs = 'abc=123&xyz=456&aaa=789'; const params = new URLSearchParams(qs); params.append('bbb', 963); .toString()) // 结果 // abc=123&xyz=456&aaa=789&bbb=963
删除
const {URLSearchParams} = require('url'); const qs = 'abc=123&xyz=456&aaa=789'; const params = new URLSearchParams(qs); ()); // 结果 // abc=123&xyz=456&aaa=789
返回迭代器的条目
const {URLSearchParams} = require('url'); const qs = 'abc=123&xyz=456&aaa=789'; const params = new URLSearchParams(qs); for (let v of params.entries()) console.log(v ); // 结果 /* [ 'abc', '123' ] [ 'xyz', '456' ] [ 'aaa', '789' ] */
forEach for all 循环
const {URLSearchParams} = require('url'); const qs = 'abc=123&xyz=456&aaa=789'; const params = new URLSearchParams(qs); params.forEach((value, key, p) => { console. log(value, key, p); }) // 结果 /* 123 abc URLSearchParams { 'abc' => '123', 'xyz' => '456', 'aaa' => '789' } 456 xyz URLSearchParams { 'abc' => '123', 'xyz' => '456', 'aaa' => '789' } 789 aaa URLSearchParams { 'abc' => '123', 'xyz' => '456', 'aaa' => '789' } */
get 返回参数键的值
const {URLSearchParams} = require('url'); const qs = 'abc=123&xyz=456&aaa=789'; const params = new URLSearchParams(qs); //结果 // 123
getAll 返回参数键的所有值
由于我们正在讨论它与 get 的不同之处,因此我创建了两个示例。
const {URLSearchParams} = require('url'); const qs = 'abc=123&xyz=456&aaa=789'; const params = new URLSearchParams(qs) console.log(params.getAll('abc')); // [ '一二三' ]
const {URLSearchParams} = require('url'); const qs = 'abc=123&xyz=456&aaa=789&abc=777'; const params = new URLSearchParams(qs); / 结果 // [ '123', '777' ]
URLSearchParams 对象允许重复键,因此提供了 getAll 方法。
顺便说一句,在 get 方法的情况下,规范是返回重复键中第一个注册的键,因此该值可能只能在 getAll 或循环内访问。
检查是否存在
const {URLSearchParams} = require('url'); const qs = 'abc=123&xyz=456&aaa=789'; const params = new URLSearchParams(qs); //结果 // 正确
键返回键的迭代器
const {URLSearchParams} = require('url'); const qs = 'abc=123&xyz=456&aaa=789'; const params = new URLSearchParams(qs); for (let k of params.keys()) console.log(k ); // 结果 /* abc xyz aaa */
设置为覆盖
const {URLSearchParams} = require('url'); const qs = 'abc=123&xyz=456&aaa=789'; const params = new URLSearchParams(qs); params.set('vvv', 247); .toString()); // 结果 // abc=123&xyz=456&aaa=789&vvv=247 params.set('vvv', 247); console.log(params.toString()); =456&aaa=789&vvv=247
如果对应的key不存在,则执行相当于append的动作,如果key存在,则覆盖key的内容。
如果存在多个键,则似乎将它们全部删除后追加。
const qs = 'a=1&a=2&a=3'; const params = new URLSearchParams(qs); // 此时 // a=1&a=2&a=3 params.set ('a', 4); console.log(params.toString()); // 结果 // a=4
破坏性排序
按名称对对象的内容进行排序。
看来逆向排序是不可能的。
请注意,它不会返回重新排列对象的 URLSearchParams 对象,而是重新排列执行对象的顺序(尽管顺序不是您真正关心的)。
const {URLSearchParams} = require('url'); const qs = 'abc=123&xyz=456&aaa=789'; const params = new URLSearchParams(qs); ; console.log(params.toString()); // 结果 // 执行前 // abc=123&xyz=456&aaa=789&vvv=247 // 执行后 // aaa=789&abc=123&vvv=247&xyz=456
值返回值的迭代器
const {URLSearchParams} = require('url'); const qs = 'abc=123&xyz=456&aaa=789'; const params = new URLSearchParams(qs); for (let v of params.values()) console.log(v ); // 结果 /* 789 123 247 456 */
URLSearchParams 对象本身是可迭代的
const {URLSearchParams} = require('url'); const qs = 'abc=123&xyz=456&aaa=789'; const params = new URLSearchParams(qs); for (const [k, v] of params) console.log(k , v); // 结果 /* aaa 789 abc 123 vvv 247 xyz 456 */
概括
我总结了WHATWG URL API和URLSearchParams,它们在以后的URL解析中将发挥重要作用。希望你已经理解了。
围绕查询字符串的实现虽然非常麻烦,但似乎正在取得进展。
就是这样。