Js是单线程的,执行机制是Event-Loop
同步、异步
Js最初设计是浏览器提交表单使用的,如果是多线程,会导致多个线程对同一个DOM进行操作,出现混乱。
Js是一行一行从上到下执行,如果上一行没有执行完成下一行就不会执行,页面会出现卡顿等现象,所以出现了异步
进程、线程
进程是一个独立的体系,线程是合力完成一个需求
1.chrome新开的一个窗口,是进程
2.窗口(进程间)如何通信?
storage | cookie 区别:
出现时间:cookie在js就有,storage在h5
存储大小:cookie为4kb,storage为20MB
前后端交互:cookie前后端交互可以携带,storage不会需要配置携带
过期时间:cookie会话级,页面关闭消失,可通过手动配置
storage(local永久,可手动清;session会话级,页面关闭消失 )不能手动配置
应用场景(登陆态cookie)=>结合项目
3.浏览器原理?
GUI渲染线程
解析HTML|CSS构建DOM树|CSSOM树=>布局=>绘制(重排、重绘)
与JS引擎线程是互斥的,当执行JS线程时,GUI定染会被挂起,当任务队列空闲时,主线程才会回去执行GUI
JS引擎线程
处理JS,解析执行脚本
分配、处理、执行待执行的脚本同时,处理待执行事件以及维护事件队列
阻塞GUI渲染 => js为何会阻塞GUI => 本职需要
事件触发线程
接收所有来源的事件
将回调的事件一次加入到任务队列的队尾,交给js引擎执行
定时器的触发线程
异步定时器的处理和执行 - setiimeout|setInterval
接收JS引擎分配的定时器任务,并执行
处理完成交由事件触发线程
异步HTTP线程
异步执行请求类操作
接收JS引擎线程异步请求操作
监听回调,交给事件触发做处理
事件Event-Loop
1.function
function fun() {
fun1();
}
function fun1() {
fun2();
}
function fun2() {
throw new Error("plz check your call stack");
}
fun();
2.setTimeout & Promise
事件分为宏任务和微任务,先执行微任务再执行宏任务
宏任务:script|setTimeout|setInterval | I/O
微任务:promise|defineProperty|Proxy
setTimeout(() => {
console.log("timeout"); //5
}, 0);
new Promise((resolve) => {
console.log("new Promise"); //1
resolve();
})
.then(() => {
console.log("Promise then"); //3
})
.then(() => {
console.log("Promise then then"); //4
});
console.log("hello"); //2
promise
1.简单链式调用
new Promise((resolve, reject) => {
console.log("promise1");
resolve("promise2");
})
.then((res) => {
console.log(res);
})
.catch((err) => {
throw new Error(err);
});
2.复合链式调用
function wait500() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("wait500");
resolve("wait500");
}, 500);
});
}
function wait1000() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("wait1000");
resolve("wait1000");
}, 1000);
});
}
const p = new Promise((resolve, reject) => {
resolve();
});
p.then(wait500).then(wait1000).then(wait500);
//全部执行完成回调
Promise.all([wait500(), wait1000()]).then((res) => {
console.log(res, "all");
});
//有执行完成的,立刻操作
Promise.race([wait500(), wait1000()]).then((res) => {
console.log(res, "race");
});
手动实现promise
1.promise状态:pending、fulfilled、rejected
2.promise默认状态是pending
状态流转:pending => fulfilled | pending => rejected
3.promise返回值 - then方法:接收onFulfilled和onRejected
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class LPromise {
constructor(executor) {
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
this.onFulfilledBack = [];
this.onRejectedBack = [];
let resolve = (value) => {
if (this.status === PENDING) {
this.status = FULFILLED;
this.value = value;
this.onFulfilledBack.forEach((fn) => fn(value));
}
};
let reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = reason;
this.onRejectedBack.forEach((fn) => fn(reason));
}
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
if (this.status === FULFILLED) {
return new LPromise((resolve, reject) => {
try {
let result = onFulfilled(this.value);
resolve(result);
} catch (error) {
reject(error);
}
});
}
if (this.status === REJECTED) {
return new LPromise((resolve, reject) => {
try {
let result = onRejected(this.reason);
resolve(result);
} catch (error) {
reject(error);
}
});
}
if (this.status === PENDING) {
return new LPromise((resolve, reject) => {
this.onFulfilledBack.push(() => {
try {
let result = onFulfilled(this.value);
resolve(result);
} catch (error) {
reject(error);
}
});
this.onRejectedBack.push(() => {
try {
let result = onRejected(this.reason);
resolve(result);
} catch (error) {
reject(error);
}
});
});
}
}
}
promise应用
const promiseArrGenerator = (num) =>
new Array(num)
.fill(0)
.map(
(item, index) => () =>
new Promise((resolve, reject) =>
setTimeout(() => resolve(index), Math.random() * 100)
)
);
const proArr = promiseArrGenerator(30);
1.有proArr数组,如何并发执行 promise
Promise.all(proArr.map(fn=>fn())).then(res=>console.log(res))
2.顺序执行promiseArrGenerator里的promise
const promiseChain = (proArr) => {
proArr.reduce((prochain,proFn)=>{
prochain.then(res=>{
~res && console.log(res)
return proFn()
)
},Promise.resovle(-1))
}
promiseChain(proArr);
3.设置一个pipe,并发执行一部分
const promisePipe = (proArr, concurrent) => {
if (proArr.length < concurrent) {
Promise.all(proArr.map((fn) => fn())).then((res) => console.log(res));
}
let _arr = [...proArr];
for (let i = 0; i < concurrent; i++) {
let fn = _arr.shift();
run(fn);
}
function run(fn) {
fn().then((res) => {
console.log(res);
if (_arr.length) run(_arr.shift());
});
}
};
promisePipe(proArr, 10);