js基础 20230302

42 阅读2分钟

请描述 event loop的机制

JavaScript是如何执行的?

  1. 自上而下,从左到右一行一行执行
  2. 如果有一行报错,后面的代码不执行
  3. 先同行步代码,在执行异步代码

Event Loop 过程

  1. 同步代码,一行一行放在Call Stack 中执行
  2. 遇到异步,会先“记录”下代码等待执行时机(setTimeout,Ajax).时机到了,将之前“记录”的代码放入Callback Queue
  3. 当 Call Stack 为空(同步代码执行完),Event Loop 开始工作
  4. Event Loop 轮询查找 Callback Queue 中是否有可执行的代码,如果有,将代码移动到CallStack 中执行
  5. EventLoop 如果没有找到可执行代码,则会继续轮询查找

image.png

演示代码


<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@说人话的前端 - bilibili</title>
  </head>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    /* 盒子模型=200+20+10
    */
    div {
      width: 500px;
      height: 200px;
      padding: 10px;
      border: 5px solid red;
      background-color: #ccc;
      box-sizing: content-box;
    }
  </style>
  <body>
    <div id="div1">说人话的前端 - bilibili</div>
    <script>
      let w = document.getElementById("div1").offsetWidth;
      console.log(w);
    </script>
  </body>
</html>

什么是宏任务和微任务?有什么区别?

什么是微任务?什么是宏任务

  1. 微任务 Promise,async,await
  2. 宏任务 setTimeout,setlnterval.Ajax,DOM事件

二者区别

  1. 先执行微任务,后执行宏任务

宏任务,微任务,DOW渲染的关系

  1. Call Stack 清空,触发Event Loop
  2. 执行微任务
  3. DOM渲染
  4. 执行宏任务

完整Event Loop过程

image.png

扩展问题

async function async1() {
  console.log('async1 start')
  await async2()
  console.log('async1 end')
}

async function async2() {
  console.log('async2')
}

console.log('script start')
setTimeout(() => {
  console.log('setTimeout')
}, 0)

演示代码

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@说人话的前端 - bilibili</title>
    <style>
      div {
        width: 200px;
        height: 200px;
        border: 5px solid red;
      }
    </style>
  </head>
  <body>
    <h1>宏任务与微任务</h1>
    <div id="div1"></div>
  </body>
  <script>
    console.log("start");
    console.log("end");
    setTimeout(() => {
      // alert("setTimeout");
      console.log("setTimeout");
    }, 0);
    Promise.resolve().then(() => {
      // alert("Promise");
      console.log("promise");
    });
  </script>
</html>


手写Promise 加载图片

出题目的

  1. 考察 lmage对象
  2. 考察 Promise
  3. 考察 async await

知识点

Image 对象

  1. new Imgage() ———— 声明一个Image对象
  2. onload ————当图片加载成功时执行
  3. onerror ————当图片加载失败时执行
  4. src ———— 设置图片路径

Promise

  1. 作用:解决回调地狱问题
  2. 语法
new Promise().then().catch()

async await

  1. 作用:Promise 的语法糖,可以增加代码可读性(用同步的思维写代码)
  2. 语法
(async function () {
  try {
    const oImg1 = await loadImg("https://robohash.org/1");
    document.body.appendChild(oImg1);
    const oImg2 = await loadImg("https://robohash.org/2");
    document.body.appendChild(oImg2);
  } catch (msg) {
    console.log(msg);
  }
})();

参考答案


const oImg = new Image();
oImg.src = "./2.jpg";

oImg.onload = function () {
  document.body.appendChild(oImg);
};

oImg.onerror = function () {
  console.log("图片加载失败");
};

function loadImg(src) {
  return new Promise((resolve, reject) => {
    const oImg = new Image();
    oImg.src = src;
    oImg.onload = function () {
      resolve(oImg);
    };

    oImg.onerror = function () {
      reject(`图片${src}加载失败`);
    };
  });
}

(async function () {
  try {
    const oImg1 = await loadImg("https://robohash.org/1");
    document.body.appendChild(oImg1);
    const oImg2 = await loadImg("https://robohash.org/2");
    document.body.appendChild(oImg2);
  } catch (msg) {
    console.log(msg);
  }
})();

loadImg("https://robohash.org/1")
  .then((oImg) => {
    document.body.appendChild(oImg);
    return loadImg("https://robohash.org/2");
  })
  .then((oImg) => {
    console.log("then2");
    document.body.appendChild(oImg);
  })
  .catch((msg) => {
    console.log(msg);
  });

Promise 阅读代码题

出题目的

  1. 考察 Promise,async,await的基础
  2. 考察对Event Loop,宏任务,微任务的理解

知识点

  1. JS执行顺序:自上而下,先同步再异步,先微任务后宏任务
  2. new Promise()=>Promise.resolve()
  3. then和catch内部没有throw new Error 相等于 rsolve
  4. async function 相当于返回 Promise.resolve()
  5. await 后面的代码都是异步代码的

题目代码


// Promise.resolve()   Promise.reject()
Promise.resolve()
Promise.reject()
	.then((data) => {
  console.log(data)
}).catch((e) => {
  console.log(e)
})

// then 和 catch 内部 throw new Error,执行后面的 catch。否则执行 then
Promise.resolve()
.then(() => {
  console.log(1);
  throw new Error("error1");
})
.catch(() => {
  console.log(2);
})
.then(() => {
  console.log(3);
});

// 相当于返回一个 Promise.resolve(100)
const p1 = async function fn1() {
  return 100;
};

p1().then((num) => {
  console.log(num);
});