ES9学习 -- 对象的剩余参数与扩展运算符 / 正则扩展 / Promise.finally / 异步迭代

文章目录

  • 1. 对象的剩余参数与扩展运算符
    • 1.1 对象的剩余参数
    • 1.2 扩展运算符
  • 2. 正则扩展
  • 3. Promise.finally
  • 4. 异步迭代
    • 4.1 同步遍历器的问题
    • 4.2 异步遍历器使用

1. 对象的剩余参数与扩展运算符

1.1 对象的剩余参数

let obj = {
name:"kerwin",
age:100,
location:"dalian"
}
let {name,...other} = obj
console.log(name,other)
function test({name,...other}){
console.log(name,other)
test(obi)

// kerwin {age:100,location: ‘dalian’}
其中…other 可以拿到对象的剩余参数

1.2 扩展运算符

let obj1= {
name:"tiechui",
location:"dalian"
}
let obj2 = {
name:"xiaoming",
age:18
}
//object.assign
let obj3 = {...obj1,...obj2}
console.log(obj3)

// {name: ‘xiaoming’,location: ‘dalian’,age: 18]

在实际开发中,我们会使用ajax() 封装一些默认的属性和属性值,以备用户忘记或未传入某些参数。

function ajax(options){
const defaultoptions = {
methods:"get",
async:true
}
options = {...defaultoptions,...options}
// 这样写会将用户传入的某些参数值覆盖某些默认参数值
console.log(options)
}
ajax({
url: "/api"
})

// { methods: “get”, async: true, url: “/api”}

2. 正则扩展

正则表达式命名捕获组

JS正则表达式可以返回一个匹配的对象,一个包含匹配字符串的类数组,比如:以Y-MM-DD的格式解析日期,这样的代码可读性很差,并且在改变正则表达式的结构的时候很有可能就会改变匹配对象的索!
ES9允许使用命名捕获 ? ,在打开捕获括号后立即命名

let str= "今天是2022-10-10"
let reg= /[0-9]{4}-[0-9]{2}-[0-9]{2}/
//exec()  捕获
cconsole.log(reg.exec(str))

在这里插入图片描述
如果想要分组单独得到年月日:

let reg= (/[0-9]{4})-([0-9]{2})-([0-9]{2}/)

在这里插入图片描述
使用reg[index] 就可以得到单独的年月日
给各个分组添加 ?<名称> 就可以使得各个分组带有意义,通过名称就可以找到各个分组。

let reg= (/?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2}/)
let {year,month,day} = res.groups
console.log(year,month,day)

// 2022 10 10

3. Promise.finally

我们之前学习Promise 时,当对象调用resolve 时会执行某些程序,调用reject 时会执行某些程序,执行这些程序之前我们要呈现加载中的状态,待到执行了程序之后我们再关闭加载的状态,这时就出现一个问题,我们想在成功或者不成功时都调用某个程序,我们需要怎么写呢?

我们可以使用finally() ,也就是我们可以将这些不论程序执行成功还是失败都要执行的代码,比如隐藏loading 写在finally() 中。

function ajax(){
return new Promise((resolve,reject)=>{
//resolve("data-1111")
reject("err-11111")
})
}
//显示 loading
ajax().then((data)=>{
console.log(data)
// 隐藏 loading
}).catch(err=>{
console.log("err",err)
// 隐藏 loading
}).final1y()=>{
console.log("finally")
//隐藏loading
})

4. 异步迭代

4.1 同步遍历器的问题

现在有一个数组,其中放了几个异步任务,需要它们按照数组任务顺序来执行,也就是上一个执行完了之后再去执行下一个任务。

function timer(t){
return new Promise(resolve=>{
setTimeout(()=>{
resolve("data-"+t)
},t)
})
}
async function test(){
let arr = [timer(1000),timer(2000),timer(3000)]
for(let item of arr){
console.log(await item)
}
test()

在这里插入图片描述
这种将异步任务放在数组中使用循环执行的情况会出现程序并发执行,并不是我们想要的效果。

如果我们将上面for 循环中的代码换成下面的代码,我们会发现第三行和第四行代码是同时出现的,也就是for 循环中的程序只有await 这一行卡住了。

for(let item of arr){
console.log("start-",Date.now())
console.log(await item)
console.log("end-",Date.now())
}

那有没有一种可能我们可以卡住整个for 循环代码快?如果第一个任务不结束,那么整个代码块都不执行;如果第一个任务结束,就让整个代码块就一起执行下来。
异步遍历器就可以实现这种任务调度的情况。

我们先来回顾一下同步遍历器!

let arr = [1,2,3]
// console.log()
let i = arr[Symbol.iterator]()
console.log(i.next())
console.log(i.next())
console.log(i.next())
console.log(i.next())
for(let i of arr){
console.log(i)
}

在这里插入图片描述

4.2 异步遍历器使用

function ajax(data){
return new Promise(resoLve=>{
resolve(data)
})
function *gen(){
yield ajax(111)
yield ajax(222)
}
let g = gen()

我们知道上面的生成器代码可以生成同步遍历器,需要使用next() 进行执行,如果next() 调用次数超过需要的次数还会报错。
这时就需要我们的异步生成器了,但是我们怎样生成异步遍历器呢?
只需要在生成器前面添加async !
异步遍历器需要通过下面的程序顺序进行。
在这里插入图片描述
我们也可以把上面异步遍历器执行代码换成下面的代码

async function test(){
let res1 = await g.next()
console.log(res1)
let res2 = await g.next()
console.log(res2)
let res3 = await g.next()
console.log(res3)
}
async function test(){
let list = [g.next(),g.next(),g.next()]
for await(let i of list){
console.log(i)
}
// 

学习过异步遍历器后,对于一开始学习异步迭代提出的问题我们可以通过下面的代码改进。

function timer(t){
return new Promise(resolve=>{
setTimeout(()=>{
resolve("data-"+t)
},t)
})
}
async function *gen(){
yield timer(1000)
yield timer(2000)
yield timer(3000)
async function test(){
let g = gen()
let arr = [g.next(),g.next(),g.next()]
for await(let item of arr){
console.log("start-",Date.now())
console.log(item)
console.log("end-",Date.now())
test()

在这里插入图片描述
注意使用for await 循环不能去循环普通的数组,会出问题的,我们一般使用这个循环去遍历由异步生成器生成的对象组成的数组。

在node 中使用任务调度使用的较多。

上一篇:BoostCompass —— 搜索引擎-一、项目简介


下一篇:使用 Django 构建简单 Web 应用