4

一、浏览器的进程和线程

      前端研发人员不要忘记了浏览器是安装在PC电脑(手机)上的应用。既然是客户端应用,就免不了一个问题:线程和进程。

  • 一个程序可以有多个进程;
  • 一个进程和多个线程;
  • 多个进程之间可以相互通信;
  • 多个线程之间可以相互通信;
  • 不同进程之间的线程不能相互通信。

      好,知道了这些基本的知识,我们来看一下浏览器(以谷歌浏览器为例)这个最基本的应用程序有哪些进程,又有哪些线程。
Chrome的进程:大家可以打开任务管理器看看,有哪些进程
clipboard.png
      从图中可以看到,在chrome中每打开一个标签页,每一个扩展程序都是一个进程。
Chrome的线程:对于一个进程来说,又有哪些线程呢?

  • GUI 渲染线程
  • JavaScript引擎线程
  • 定时触发器线程
  • 事件触发线程
  • 异步http请求线程

      那么当你打开一个页面,就启动了一个进程,那么这个进程有上面几个线程。这几个线程之间相互合作,但是GUI和JavaScript之间是相互独立的,而且Javascript是单线程的。原因很简单,涉及UI操作的不能同时处理,不然给用户呈现的页面会是什么样子。
      既然知道了,浏览器作为应用程序具备的基本要素。那么我们想看看浏览器内部具体的工作方式。
了解一个程序,首先了解程序的模块划分和工作流程。
浏览器主要划分这几个模块浏览器部件:那么这几个部件相互耦合,为用户提供页面。

  • 1、用户界面
  • 2、浏览器引擎
  • 3、渲染引擎
  • 4、网络
  • 5、用户界面后端
  • 6、Javascript解释器
  • 7、数据持久化存储

clipboard.png

二、浏览器页面渲染的方式(页面初始化)

我们重点来看一下浏览器的渲染是怎么操作的

clipboard.png

clipboard.png

三、浏览器的事件系统(页面操作)MacroMicro

clipboard.png
异步并不是不执行,而是执行放入队列。

四、案例(可能是你们最想看的)

//案例一:
setTimeout(() => {
    console.log(promise);
    console.log('settimeout1');
  }, 0);
let promise = new Promise(function(resolve, reject) {
    console.log('Promise');
    setTimeout(()=>{
        resolve('success');
    },0);
    //resolve('success');
  }).then((msg)=>{
    console.log('resolved.'+msg);
  });
  
  setTimeout(() => {
    console.log(promise);    
    console.log('settimeout2');
}, 0);
  console.log(promise);
  console.log('Hi!');
//输出结果
Promise                //Promise会立即执行
Promise { <pending> }  //此时promise状态为pending
Hi!                    //打印hi
Promise { <pending> }  
settimeout1            //主线程执行完毕,依次将三个settimeout放入macro队列中,打印第一个
Promise { <pending> }
settimeout2            //打印第二个
resolved.success       //promise执行成功

//案例二:

如果promise中直接resolve('success'),运行结果是怎么样?
Promise
Promise { <pending> }
Hi!
resolved.success
Promise { undefined }
settimeout1
Promise { undefined }
settimeout2

//案例三:

如果在React中的事件系统是什么样子的呢?
class Father extends Component {
  render() {
    let promise = new Promise(function(resolve, reject) {
      resolve('success1');
    }).then((msg)=>{
      console.log('resolved.'+msg);
    });
    return (
      <Son ref="son"/>
    );
  }
  componentDidMount(){
    console.log('Did Mount');
  }
  componentWillMount(){
    let promise = new Promise(function(resolve, reject) {
      resolve('success2');
    }).then((msg)=>{
      console.log('resolved.'+msg);
    });
    console.log('Will Mount');
  }
}

//输出结果
Will Mount
Did Mount
resolved.success2
resolved.success1
可以看到react并没有将micro任务合并到渲染里面

为什么会提及React,因为React 的处理方式和我们和浏览器的实现流程比较类似。
React初始化《======》浏览器初始加载
React更新   《======》浏览器的事件系统
所以React从很大程度上做了一层抽象,让我们面向组件的函数编程,而不是面向浏览器的编程。

附录:Node中的事件系统Node

node环境中的事件系统多了两个 process.nextTick和setImmediate

clipboard.png

//案例四:
setTimeout(() => {
    console.log(promise);
    console.log('settimeout1');
  }, 0);
let promise = new Promise(function(resolve, reject) {
    console.log('Promise');
    /*setTimeout(()=>{
        resolve('success');
    },0);*/
    resolve('success');
  }).then((msg)=>{
    console.log('resolved.'+msg);
  });
  
  setTimeout(() => {
    console.log(promise);    
    console.log('settimeout2');
}, 0);
console.log(promise);
console.log('Hi!');
process.nextTick(()=>{console.log('nextTick')});
setImmediate(()=>{console.log('Immediate')}) ;
//输出结果
Promise
Promise { <pending> }
Hi!
nextTick
resolved.success
Promise { undefined }
settimeout1
Promise { undefined }
settimeout2
Immediate

joytime
44 声望2 粉丝