1.音讯行列与实践循环
单线程处理使命的3个渐进计划
第一版
逐行履行的缺陷
- 必须提前设定好,无法半途新增
console.log("1")
console.log("2")
console.log("3")
第二版
参加while循环+ 获取输入和核算,能够一向获取输入
while(true) {
let a = prompt("请输入a:")
let b = prompt("请输入b:")
console.log(a+b)
}
第三版
- 新增音讯行列
- 跨线程处理使命
- 经过引入io线程一致转发给 烘托主线程
- 资源加载完回调:来自网络进程 经过IPC传输
- 鼠标点击回调: 来自浏览器进程 经过IPC传输
事情循环
- 增加一个音讯行列
行列
先进先出 - io线程产生新使命增加到 烘托主线程的 音讯行列
- 烘托主线程会循环读取音讯行列头使命,并履行使命
function main(){
isOver = false //是否标识了退出,默许不退出
while(true) {
const taskList = taskListForIO //使命列表为io线程传入,一向动态改变
processTask(taskList.shift())//每次取出一个使命履行
if(isOver) { //判别是否退出
break
}
}
}
//实时获取最新的来自io 线程的使命
function taskListForIO() {
const taskList = [task1,task2]
///.. 这儿省掉 io 新增使命的逻辑
return taskList //
}
//处理使命
function processTask(task) {
//...
}
- 退出策略
增加一个标识,每次循环查看是否能够退出
音讯行列类型
单线程履行的缺陷
- 实时同步履行会严重拖慢后边排队的使命
- 优先级无法默许排在音讯行列尾部,履行机遇太晚
- 监听dom实时改变的函数 MutationObserver
- 同步太频频
- 异步履行机遇太晚
处理计划
微使命
- 每个宏使命都包括一个微使命行列,
- 每次宏使命履行完之前都会清空微使命
2.WebAPI:setTimeout是怎么完成的?
常见的音讯循环事情
- 浏览器接收并解析html文档,解析dom事情
- 改动windows窗口大小事情
- 垃圾收回事情
- setTimeout的事情
settimeout完成
- 在每次事情循环处理完 processTask后,都会调用一遍ProcessDelayTask,如果当前有使命现已满意时刻,则出发对应的回调办法
- 缺陷:当前面有个长使命再跑,processDelayTask履行机遇会被延后
DelayTask timerTask;
timerTask.cbf = showName;
timerTask.start_time = getCurrentTime(); // 获取当前时刻
timerTask.delay_time = 200;// 设置推迟履行时刻
//增加使命
DelayTaskList.push(timerTask);
//代码履行
void ProcessDelayTask(){
// DelayTaskList 中取出现已到期的定时器使命
// 顺次履行这些使命
}
function main(){
isOver = false //是否标识了退出,默许不退出
while(true) {
const taskList = taskListForIO //使命列表为io线程传入,一向动态改变
processTask(taskList.shift())//每次取出一个使命履行
ProcessDelayTask()// 履行推迟行列中的使命
if(isOver) { //判别是否退出
break
}
}
}
//实时获取最新的来自io 线程的使命
function taskListForIO() {
const taskList = [task1,task2]
///.. 这儿省掉 io 新增使命的逻辑
return taskList //
}
//处理使命
function processTask(task) {
//...
}
- 当settimeout 循环嵌套履行超过5次,chrome会强制把距离时刻调整为 最小距离4秒
- 未激活的页面 settimeout履行最小时刻距离是1秒
settimeout的最大值
- 32个bit 2147483647毫秒即 24.8天
- 超出这个范围后就会溢出,变成当即履行
settimeout的this 指向
默许指向window,修正办法
- 经过箭头函数
- 经过 bind
3.xmlhttprequest 与 回调函数
回调函数
函数作为参数传入其他一个函数,这个参数便是回调函数
同步履行的回调
let callback = function(){
console.log('i am do homework')
}
function doWork(cb) {
console.log('start do work')
cb()
console.log('end do work')
}
doWork(callback)
异步回调
let callback = function(){
console.log('i am do homework')
}
function doWork(cb) {
console.log('start do work')
setTimeout(cb,1000)
console.log('end do work')
}
doWork(callback)
两种方法
- 宏使命回调
- 微使命回调
xmlhttprequest
流程
- 烘托进程 经过IPC 告诉网络进程下载
- 网络进程下载完 经过IPC告诉io线程参加音讯行列
- 烘托线程挨个取出宏使命履行
xhr.responseType=”text” 控制不同的配置回来信息
4.微使命
宏使命的缺陷
宏使命不能接连履行
function fun1(){
console.log(1)
setTimeout(fun2)
}
function fun2(){
console.log(2)
}
setTimeout(fun1,0)
//履行完fun1 后,fun2并不是紧跟着履行,中心会交叉许多其他宏使命
履行流程
- 烘托事情(如解析DOM、核算布局、制作)
- 用户交互事情(如鼠标点击、翻滚页面、放大缩小等)
- JavaScript脚本履行事情
- 网络请求完结、文件读写完结事情
每个宏使命都包括一个微使命行列
触发的办法
- mutationObserver
- Promise
微使命行列保存在全局履行上下文
当全局履行上下文快退出前,履行所有微使命行列
监听DOM改变的函数
- 1.MutationEvent
- 同步实时回调,观察者形式,会堵塞后边的宏使命履行
-
- MutationObserver
- 节流的作用,终究一次才触发异步回调,防止当前宏使命
- 放入微使命行列,完成了实时调用性
- MutationObserver
5.Promise
异步编程的缺陷
- 代码不接连问题
- 阴间回调
比如
let xhr = new XMLHttpRequest()
xhr.ontimeout = function(e) { onReject(e)}
xhr.onerror = function(e) { onReject(e) }
xhr.onreadystatechange = function () { onResolve(xhr.response) }
//优化 经过优化xmlhttprequest
XFetch(makeRequest('https://www.test.com'),
function resolve(data) {
console.log(data)
}, function reject(e) {
console.log(e)
})
- 简化回调只剩 resolve 和 reject 两个办法
- 缺陷 嵌套多的时候依然有回调阴间问题
Promise处理了什么
- 消灭嵌套调用
- Promise完成了回调函数的延时绑定
// 创立 Promise 目标 x1,并在 executor 函数中履行业务逻辑
function executor(resolve, reject){
resolve(100)
}
let x1 = new Promise(executor)
//x1 推迟绑定回调函数 onResolve
function onResolve(value){
console.log(value)
}
x1.then(onResolve)
2.合并多个使命的错误处理
– 需要将回调函数onResolve的回来值穿透到最外层
使用方法
function XFetch(request) {
function executor(resolve, reject) {
let xhr = new XMLHttpRequest()
xhr.open('GET', request.url, true)
xhr.ontimeout = function (e) { reject(e) }
xhr.onerror = function (e) { reject(e) }
xhr.onreadystatechange = function () {
if (this.readyState === 4) {
if (this.status === 200) {
resolve(this.responseText, this)
} else {
let error = {
code: this.status,
response: this.response
}
reject(error, this)
}
}
}
xhr.send()
}
return new Promise(executor)
}
//调用
var x1 = XFetch(makeRequest('https://www.test.com/?category'))
var x2 = x1.then(value => {
console.log(value)
return XFetch(makeRequest('https://www.test.com/column'))
})
var x3 = x2.then(value => {
console.log(value)
return XFetch(makeRequest('https://www.test.com'))
})
x3.catch(error => {
console.log(error)
})
完成2个作用
1.回调函数的推迟绑定,完成代码嵌套履行变成 按序履行,而且回调办法定义也能够写在调用的后边书写。
// 创立 Promise 目标 x1,并在 executor 函数中履行业务逻辑
function executor(resolve, reject){
resolve(100)
}
let x1 = new Promise(executor)
//x1 推迟绑定回调函数 onResolve
function onResolve(value){
console.log(value)
}
x1.then(onResolve)
- 把成功回调函数包装成Promise 回来,穿透到最外层,完成异常外抛, catch只是语法糖,终究等价于
Promise.proptotype.catch = function(callback) {
return this.then(null,callback)
}
终究代码
function MyPromise(executor) {
var onResolve_ = null
var onReject_ = null
// 模拟完成 resolve 和 then,暂不支撑 rejcet
this.then = function (onResolve, onReject) {
onResolve_ = onResolve
};
function resolve(value) { //函数resolve 作为一等公民做参数 被下面executor调用
// setTimeout(()=>{// 这儿利用宏使命的特性完成推迟履行
onResolve_(value)
// },0)
}
executor(resolve, null);//这儿的resole 参数是 经过后边的then传入
}
function executor(resolve, reject) {
resolve(100) //按正常履行,这儿会当即履行,也便是 MyPromise 内部现已定义好的resolve办法。
}
//实例化Mypromise 就会立马履行executor
let demo = new MyPromise(executor) //这儿分离的嵌套的函数,完成再下面代码才定义和绑定
function onResolve(value){
console.log(value)
}
demo.then(onResolve) //这儿的回调推迟到调用then才绑定
自定义组件怎么监听dom并作出呼应
- 经过settimeout 和 setIinterval主动查询dom是否改变
- mutation event
- 经过观察者形式实时,同步履行代码
- 简单导致其他动画卡顿
- MutationObsever
- 经过微使命履行dom呼应事情
参阅
time.geekbang.org/column/intr…