关于javascript:浏览器工作原理与实践四

31次阅读

共计 2533 个字符,预计需要花费 7 分钟才能阅读完成。

音讯队列:单行道 -> 先进先出。又被称为宏工作,执行宏工作的时候,如果 DOM 有变动,将变动提交到工作中。当宏工作执行完再执行微工作。优先级问题。
音讯队列和事件循环相似于观察者公布订阅模式,事件循环 (单线程运行过程中能接管并执行新工作) 是按程序执行音讯队列中工作的。for
主线程——> 音讯队列。主线程——> 音讯队列——> 音讯队列中微工作。
音讯队列中工作:解析 DOM 事件、从新布局事件、垃圾回收工作、IO 工作、点击事件。
定时器须要在指定距离能力调用回调函数。不能间接增加到音讯队列,只能放在提早队列。
音讯队列执行完会执行提早队列,嵌套调用最短时间为
setTimeout 是将提早工作增加到提早队列中,XMLHttpRequest 发动申请是由浏览器的网络过程去执行,再将后果利用 IPC 形式通过渲染过程再增加到音讯队列。
页面中大部分工作都是在主线程执行的:

  1. 渲染事件(解析 DOM、计算布局、绘制)
  2. 用户交互事件(鼠标点击、滚动页面、放大放大等)
  3. JS 脚本执行事件
  4. 网络申请实现,文件读写实现事件
    渲染过程外部会有多个音讯队列,比方提早和一般的音讯队列。而后主线程采纳 for 循环,一直从这些工作队列中取出工作并执行工作。音讯队列中的工作叫宏工作,音讯队列中的工作是通过事件循环来执行的。setTimeout 的函数触发也都在宏工作。为了执行工夫精度的管制,Promise 执行放到微工作,以后执行完执行微工作而后再执行宏工作,所以比 setTimout 快。
    微工作中的微工作,在微工作执行之后,继续执行微工作。
    在以后宏工作中的 JS 快执行实现时,JS 引擎筹备退出全局执行上下文,并清空调用栈时,JS 引擎会查看全局执行上下文的微工作队列,而后程序执行微工作。微工作是 V8 引擎在创立全局执行上下文时创立的队列,当有微工作时再寄存进去。
    监听 DOM,MutationObserver 将响应函数改成异步,等屡次 DOM 变动后,合成一次触发异步调用,微工作告诉变动,异步 + 微工作。
    Promise 的呈现是扭转回调的编码格调,但它 excutor 和 then 外面用的还是回调函数。
    模仿 Promise:
function Bromise(executor){
    var onResolve=null;
    var onReject=null;
    this.then=function(onResolve,onReject){onResolve=onResolve;}
    funtion resolve(value){setTimeout(()=>{onResolve(value)},0)
    }
    executor(resolve,null)
}
调用:function executor(resolve,reject){resolve(100)
};
let demo=new Bromise(executor);
function onResolve(value){console.log(value)
}
demo.then(onResolve);

Promise 通过回调函数提早绑定,回调函数返回值穿透和谬误冒泡技术解决了多层嵌套和谬误捕捉。

Generator

生成器 Generator 函数是一个带星号的函数,能够暂停执行和复原执行的。
协程是比线程更加轻量级的存在,一个线程上能够存在多个协程,但同期只能执行一个协程,如果从 A 协程启动 B 协程,A 就是 B 的父协程,协程由用户管制执行。

function* genDemo(){console.log('执行第一段');
    yield 'generator1';
    console.log('执行第二段');
    yield 'generator2';
    console.log('执行完结');
    return 'generator3'
}
console.log('main0');
let gen=genDemo();
console.log(gen.next().value);
console.log('main1');
console.log(gen.next().value);
console.log('main2');
console.log(gen.next().value);
console.log('main3');

输入后果全局和 genDemo 交替执行,生成器个性能够暂停,复原执行。

  1. 生成器外部执行一段代码,遇到 yield,JS 引擎返回前面的内容给内部,并暂停
  2. 内部函数能够通过 next 复原函数执行。(1)通过调用 genDemo 创立一个协程 gen,创立后 gen 协程没有立刻执行。(2)让 gen 协程执行,要通过调用 gen.next()。(3)当协程正在执行的时候,通过 yield 来暂停 gen 协程的执行,并返回次要信息给父协程。(4)协程执行期,遇到 return,JS 引擎会完结以后协程,将 return 前面的内容返回给父协程。

    async

    async/await: 应用了同步的形式写异步代码

    async function foo() {console.log(1)
     let a=await 100;
     console.log(a);
     console.log(2)
    }
    console.log(0)
    foo();
    console.log(3)
  3. 执行 console.log(0)打印 0
  4. 执行 foo,因为被 async 标记过,JS 引擎会保留以后调用栈,执行 console.log(1)
  5. 执行 await 100,JS 会创立一个 promise,let promise=new Promise(resolve,reject){resolve(100)},JS 引擎将工作提交给微工作队列 promise。
  6. JS 引擎暂停以后协程执行,将主线程控制权交给父协程,同时将 promise 对象返回给父协程
  7. 主线程控制权给过父协程,父协程要调 promise.then 来监控 promise 状态的扭转
  8. 接下来持续父协程流程执行,执行 console.log(3),父协程执行完结,完结之前进入微工作查看,执行微工作,resolve(100),resolve 回调函数被激活后,将主线程控制权交给 foo 函数的协程,将 value 值传给该协程
  9. foo 协程激活后,把 value 值给 a,而后 foo 协程继续执行 console.log(a),console.log(2)

正文完
 0