美文网首页
进程-线程-事件循环

进程-线程-事件循环

作者: 未路过 | 来源:发表于2022-09-30 22:59 被阅读0次

    19.1 进程和线程

    161.PNG 162.PNG 163.PNG

    19.2 浏览器中的Javascript线程

    浏览器的每一个tab页面就会开启一个新的进程,这个进程里面有包括执行js代码的单线程,也有执行其他操作的线程。比如网络请求,定时器什么的都是其他线程执行的。js单线程就是指同一时刻只能执行一段,一行js代码。不能同时执行不同行的js代码。

    164.PNG

    19.3 浏览器的事件循环

    165.PNG 167.PNG
    console.log("script start")
    
    // 业务代码
    setTimeout(function() {
    
    }, 1000)
    //定时器函数,是全局函数,这个函数本身不是异步操作,是同步,像foo函数被调用一样
    //是同步调用,但是setTimeout需要传进去一个回调函数,一般说的异步函数,是指的是传进去的这个函数
    /* 
    传进去的这个函数不是立即执行,1s之后执行,
    浏览器的其他线程帮助我们开始计时操作,
    js线程是单线程的,如果计时的话,其他就不能操作了。
    这个回调函数会保存到js的其他线程,
    js线程不用管你,开始执行其他行的代码
    等到1s中的时候,开始执行回调函数
    这个时候是有一个队列的,浏览器本身维护着一个队列queue(事件队列)
    队列是一种数据结构,是先进先出。跟栈结构相反,
    队列默认没有东西,当计时器达到1s后,会将回调函数放到队列里面
    当js引擎发现队列有东西,就会从队列里面取出我们要执行的回调函数
    开始做执行
    
    网络请求,settimeout,dom操作都可以依次加到队列里面
    
    加到队列后,从队列里面挨个取出函数并且调用,在js里面执行,
    
    真正执行的位置还是js的线程。
    
    一般情况下,
    js线程,浏览器的其他线程,浏览器维护的事件队列
    这三个东西形成了一个闭环。
    
    回调函数之类的放到浏览器的其他地方做一些耗时操作,
    耗时操作结束之后,会将回调函数加入到队列里面
    js线程再从队列里面获取到要执行的回调函数,开始进行执行
    
    这个闭环,就被我们成为事件循环
    
    无论是网络请求,还是settimeout都是由js线程发起的,
    然后再js的其他线程做耗时操作,并且加到队列里面,最后再返回js线程执行
    */
    
    console.log("后续代码~")
    
    
    console.log("script end")
    
    

    19.4 宏任务和微任务

    166.PNG
    setTimeout(() => {
      console.log("setTimeout")
    }, 1000)
    //setTimeout是先放到浏览器的其他线程,等到时间之后,加入到队列里面
    
    queueMicrotask(() => {
      console.log("queueMicrotask")
    })
    //queueMicrotask是直接加入到队列里面,并且和settimeout加入的是不同的队列
    
    /* 
    
    宏任务队列(macrotask queue):ajax、setTimeout、setInterval、DOM监听、UI Rendering等
    微任务队列(microtask queue):Promise的then回调、 Mutation Observer API、queueMicrotask()等
    
    规范:
    当两个队列里面都有任务的时候,
    在执行任何的宏任务之前,都需要先保证微任务队列已经被清空
    
    
    
    */
    
    
    Promise.resolve().then(() => {
      console.log("Promise then")
    })
    
    
    //以下是main script 全局代码,优先执行
    function foo() {
      console.log("foo")
    }
    
    function bar() {
      console.log("bar")
      foo()
    }
    
    bar()
    
    console.log("其他代码")
    
    

    19.5 面试题

    1.面试题1

    setTimeout(function () {
      console.log("setTimeout1");
      new Promise(function (resolve) {
        resolve();
      }).then(function () {
        new Promise(function (resolve) {
          resolve();
        }).then(function () {
          console.log("then4");
        });
        console.log("then2");
      });
    });
    
    new Promise(function (resolve) {
      console.log("promise1");
      resolve();
    }).then(function () {
      console.log("then1");
    });
    
    setTimeout(function () {
      console.log("setTimeout2");
    });
    
    console.log(2);
    
    queueMicrotask(() => {
      console.log("queueMicrotask1")
    });
    
    new Promise(function (resolve) {
      resolve();
    }).then(function () {
      console.log("then3");
    });
    
    
    /* 
    new Promise((resolve, reject) => {
      ...
    })
    
    在这里,
    (resolve, reject) => {
      ...
    }
    这个回调函数是不会被加进任务队列的,是会直接执行的
    相当于里面代码...在main script里面执行的
    后面的then里面的回调是会被加入进微任务队列的
    等到下面单线程的代码运行完之后才能够执行
    
    */
    /* 
    
    "promise1"
    2
    then1
    queueMicrotask1
    then3
    setTimeout1
    "then2"
    then4
    setTimeout2
    */
    
    
    /* 
    
    执行完微任务之后,执行
    setTimeout(function () {
      console.log("setTimeout1");
      new Promise(function (resolve) {
        resolve();
      }).then(function () {
        new Promise(function (resolve) {
          resolve();
        }).then(function () {
          console.log("then4");
        });
        console.log("then2");
      });
    });
    
    先输出"setTimeout1",之后,直接执行function (resolve) {
        resolve();
      }
      然后,把这个回调函数
      function () {
        new Promise(function (resolve) {
          resolve();
        }).then(function () {
          console.log("then4");
        });
        console.log("then2");
      }
      加入到微任务中
      这时候,就剩下了微任务中的这个,还有宏任务中的setTimeout2
      在执行宏任务之前,要保证微任务里面没有东西,
      所以需要先执行上面的回调
      执行resolve(),然后再把then4加入到微任务
      然后再继续往后,执行then2
      接下来再执行then4,后面执行settimeout2
    
    */
    

    [图片上传失败...(image-f5de6d-1664549933477)]

    2.面试题2

     async function bar() {
       console.log("22222")
      return new Promise((resolve) => {
         resolve()
       })
     }
    
     async function foo() {
       console.log("111111")
    
       await bar()
    
       console.log("33333")
     }
    
     foo()
     console.log("444444")
    
     /* 
     
     111111
    test2.html:15 22222
    test2.html:30 444444
    test2.html:26 33333
     */
    
    
    async function async1 () {
      console.log('async1 start')
      await async2();
      console.log('async1 end')
    }
    
    async function async2 () {
      console.log('async2')
    }
    
    console.log('script start')
    
    setTimeout(function () {
      console.log('setTimeout')
    }, 0)
     
    async1();
     
    new Promise (function (resolve) {
      console.log('promise1')
      resolve();
    }).then (function () {
      console.log('promise2')
    })
    
    console.log('script end')
    
    
    /* 
    script start
    'async1 start'
    async2
    'promise1'
    'script end
    async1 end
    promise2
    setTimeout
    */
    

    3.面试题3

    Promise.resolve().then(() => {
      console.log(0);
        // 1.直接return一个值 相当于resolve(4)
    
      return 4
    }).then((res) => {
      console.log(res)
    })
    
    Promise.resolve().then(() => {
      console.log(1);
    }).then(() => {
      console.log(2);
    }).then(() => {
      console.log(3);
    }).then(() => {
      console.log(5);
    }).then(() =>{
      console.log(6);
    })
    
    /* 
    0
    1
    4
    2
    3
    5
    6
    
    */
    
    Promise.resolve().then(() => {
      console.log(0);
       // 2.return thenable的值
      return {
        then: function(resolve, reject){
          resolve(4)
        }
      }
      //,本来是直接resolve(4)的,但是因为是thenable,执行这个then函数被放到了下一次的为任务中
    }).then((res) => {
      console.log(res)
    })
    
    Promise.resolve().then(() => {
      console.log(1);
    }).then(() => {
      console.log(2);
    }).then(() => {
      console.log(3);
    }).then(() => {
      console.log(5);
    }).then(() =>{
      console.log(6);
    })
    
    /* 
    0
    1
    2
    4
    3
    5
    6
    
    */
    
    Promise.resolve().then(() => {
      console.log(0);
     // 3.return Promise
      // 不是普通的值, 多加一次微任务
      // Promise.resolve(4), 多加一次微任务
      // 一共多加两次微任务
      return Promise.resolve(4)
    }).then((res) => {
      console.log(res)
    })
    
    Promise.resolve().then(() => {
      console.log(1);
    }).then(() => {
      console.log(2);
    }).then(() => {
      console.log(3);
    }).then(() => {
      console.log(5);
    }).then(() =>{
      console.log(6);
    })
    
    /* 
    0
    1
    2
    3
    4
    5
    6
    
    */
    

    19.6 Node中的事件循环

    169.PNG 170.PNG

    19.7 Node事件循环的阶段

    171.PNG 172.PNG
    173.PNG 174.PNG

    相关文章

      网友评论

          本文标题:进程-线程-事件循环

          本文链接:https://www.haomeiwen.com/subject/vyvrartx.html