async+await 事件循环 defineProperty
一、async+await
ES7: 提供了 async 和 await 语法糖, 提供一种新的写法(属于ES6的 Generator 语法的语法糖)
demo
// 1. 同步执行的 异步操作必须放在 async 修饰的函数里
async function getData() {
// async:异步的 await:等待
// res1: 相当于 Promise 的 then 中收到的结果
// 依赖try...catch语法来抓取报错
try {
var res1 = await fetch(url1).then(res => res.json())
console.log(res1)
var res2 = await fetch(url2).then(res => res.json())
console.log(res2)
var res3 = await fetch(url3).then(res => res.json())
console.log(res3)
} catch (error) {
console.log(error)
}
}
如果在请求中只发一个请求,用Promise就行
如果连续发送多个请求,使用async+await的语法糖会比promise的.then()链式写法更加的直观易读
二、事件循环(eventloop)
事件循环: JS代码在运行时的具体方式:主线任务 + 支线任务: 主线优先, 支线其次
支线任务 是在执行主线任务时 额外诞生的
专业说法:
JS分 宏任务(主) 和 微任务(支)
所有的微任务 都是 宏任务在执行过程中 伴随诞生的(即不会单独出现微任务)
微任务: 都是一些完成时机不确定的异步操作
-
Promise的then;
-
await; 回调函数
-
定时器
完成时机不确定:定时器为什么完成时机确定,因为事件循环是js在静态分析代码阶段对代码进行宏任务与微任务的划分,定时器只有在js的运行阶段才会知道具体需要的时间,本质和promise的.then()一样的只有具体运行才能知道需要的时间。因此叫做时机不确定的异步操作
webworker
js是单线程的语言,又存在宏任务与微任务的划分,这就导致一些回调函数会在主线任务过于繁多(或过于耗时)时无法执行。webworker可以创建一个新的线程,我们可以将一些较为复杂的代码,放到这个新的线程中运行,这样就防止页面的卡顿
demo
//单独js文件存放复杂代码
// 把复杂的JS代码, 单独存放在 js文件里
function Fibonacci(n) {
return n < 3 ? 1 : Fibonacci(n - 1) + Fibonacci(n - 2)
}
var r = Fibonacci(45)
console.log({ r })
// 把执行后的结果 全局通知
postMessage({ r })
// post: 传递,传送
// message: 消息
//主文件中
// 使用 WebWorker 创建一个新的线程, 来单独执行复杂的 耗时的JS代码, 可以防止页面的卡顿
const w = new Worker('./test.js')
// 接收消息
w.onmessage = function (e) {
console.log("消息:", e);
// 传递的消息内容在 e.data 中
res.innerHTML = e.data.r
}
// worker:工人; 创建一个单独的工人, 来执行 test.js 中的代码
三、defineProperty
defineProperty\defineProperties
作用: 为指定对象的属性, 添加个性化配置
语法:Object.defineProperty(‘对象’,‘属性名’,{配置项})
Object.defineProperties(‘对象’,{属性名1:{配置项},属性名2:{配置项},属性名3:{配置项})
3.1,writable
writable:配置项,可重新写入的,默认为true
Object.defineProperty(emp, 'eid', {
writable: false, // 可写?? : 假的 - 不可以
// 是否可以写入新的值
})
3.2,configurable
configurable:配置项,可重新配置的,默认为true
Object.defineProperties(emp, {
// configurable: 是否可以重新配置
// false: 代表不可以重新配置, 即无法删除属性
name: { writable: false, configurable: false }
})
3.3,enumerable
enumerable:配置项,可遍历,默认为true
// 让 salary 属性无法被 for...in 遍历出来
Object.defineProperties(emp, {
salary: { enumerable: false }, //是否可以被遍历?? false不可以
})
3.4,value
value:配置项,默认值
Object.defineProperties(emp, {
// 1. 修改age的值
age: { value: 100 },
// 如果配置的属性不存在, 则自动新增
// 特点: 此方式新增的属性所有权限 都是关闭的. 不可遍历,不可配置,不可写入新值
// 可以自定义开启一些权限
})
3.5,计算属性-defineProperty的set与get方法实现
get()使用,新增属性
var r1 = {
width: 100,
height: 40
}
Object.defineProperties(r1, {
// area
area: {
// get: function () { }
get() { return this.width * this.height }
},
zc: {
get() { return (this.width + this.height) * 2 }
}
})
console.log(r1, r1.area, r1.zc)
set()使用,赋值监听
let emp = {
name:'kaikai'
}
Object.defineProperties(emp,{
_phone:{
value:'13212345678',
writable:true
},
phone:{
get(value){
return this._phone
},
set(value){
if(typeof(value) == 'string'){
if(/^1[3-9]\d{9}$/.test(value)==true){
this._phone=value
}else{
throw Error('格式不对')
}
}else{
throw Error('类型不对')
}
}
}
})
console.log(emp.phone);
emp.phone = '13812345678'
console.log(emp.phone);
尝试使用defineProperty的set与get方法实现vue的数据驱动
数据驱动: 监听 data中每个元素的赋值操作, 同步更新DOM元素
遍历data中的每个属性, 都改造成 带监听的方法
<body>
<div id="app">
<h1 v-text="count"></h1>
<button onclick="data.count++">count++</button>
<button onclick="data.count--">count--</button>
<h1 v-text="name"></h1>
</div>
<script>
let data = {
count : 10,
name:'kaikai'
}
for(let key in data){
Object.defineProperties(data,{
[`_${key}`]:{
writable:true,
value:data[key]
},
[`${key}`]:{
get(value){
return this[`_${key}`]
},
set(value){
this[`_${key}`]=value
//当赋值操作发生时,立刻更新DON
updataDOM()
}
}
})
}
function updataDOM(){
for(let key in data){
// console.log({key});
let x = `[v-text=${key}]`
// console.log({x});
let els = document.querySelectorAll(x)
// console.log(els);
els.forEach(el=>el.innerText=data[key])
}
}
updataDOM()
</script>
</body>