JS 是单线程的

  • 同步是指,任务是按照顺序依次处理的,一步步执行,当前事件没有处理完成,下一件事执行不了

  • 异步是指,当前事件没有彻底做完,需要等待一段时间才能继续处理,此时不会等待其完成,继续执行下面任务,当后面的任务完成后,再去把没有彻底完成的事情完成

常见的异步编程:

  • 定时器

  • 事件绑定

  • AJAX 请求一般都使用异步编程处理

1. 浏览器规划同步异步机制

  • (1)浏览器是多线程的,JS 是单线程的(浏览器只给 JS 执行分配一个线程):单线程的特点就是一次只能处理一件事情

    • 进程:每一个应用程序启动的时候都会开辟一个进程(浏览器打开一个页面就相当于开辟一个进程),

    • 线程:在一个程序中(进程中),我们经常会同时干很多事情,此时我们可以分配多个线程去同时完成多项任务

  • (2)JS 在单线程中实现异步的机制,主要依赖于浏览器的任务队列来完成的,浏览器有两个任务队列:主任务队列、等待任务队列。

    • 主任务队列指的是同步代码从上而下执行

    • 等待任务队列存放的是异步代码,等待任务队列中的代码执行的前提是主任务队列中的代码执行完毕

  • (3)在主任务队列自上而下执行时,遇到一个异步操作的任务,没有立即执行,而是把它放到等待任务队列中排队
  • (4)当主任务队列完成后才会到等待任务中进行查找(主任务完不成,不管等待任务队列中是否有到达时间的,都不处理,继续等待主任务队列完成,因为 JS 是单线程的,一次只能处理一件事情)
  • (5)等待任务队列中,谁达到条件了(如果有很多都达到条件了,先达到的先处理),就把这个任务重新放到主任务队列中去执行,把这个任务执行完,再去等待中查找

设置定时器本身是同步的,但是里面执行的代码是异步的,就诞生一个异步任务,会放到等待任务队列中。

2. 查看代码执行时间

大概计算代码执行时间的方法:

  • 使用开始和结束的时间记录,然后相减

  • 使用 console.time('标记')console.timeEnd('标记')

  1. let startTime = new Date();
  2. for (let i = 0; i < 9000; i++) {
  3. }
  4. let endTime = new Date();
  5. console.log(new Date - startTime);
  6. //=> 从记录标记到结束标记经历的时间
  7. console.time('AA');
  8. for (let i = 0; i < 90000000; i++) {
  9. }
  10. console.timeEnd('AA');

3. 练习

题目一:

  1. setTimeout(() => {
  2. console.log(1);
  3. }, 1000);
  4. console.log(0); // 先输出 0,再输出 1

题目二:

  1. //=> 定时器设定一个时间,到达时间后不一定执行(如果当前还有其它同步任务正在处理,那么到时间也必须等待)
  2. setTimeout(() => {
  3. console.log(1);
  4. }, 1000);
  5. console.log(0);
  6. while(true) {
  7. //=> 死循环
  8. }
  9. //=> 只能输出 0,,不能执行定时器的事情

题目三:

  1. //=> 先不用管异步代码,先执行同步代码,全部执行完成后再看异步的代码谁先完成,就先执行谁
  2. setTimeout(()=>{
  3. console.log(1);
  4. }, 20);
  5. console.log(2);
  6. setTimeout(()=>{
  7. console.log(3);
  8. }, 10);
  9. setTimeout(()=>{
  10. console.log(4);
  11. }, 100);
  12. for (let i = 0; i < 9000; i++) {
  13. }
  14. console.log(5);
  15. //=> 2 5 3 1 4

题目四:

  1. let n = 0;
  2. setTimeout(()=>{
  3. console.log(++n);
  4. }, 0); //=> 定时器时间设置为 0 也不是立即执行,每个浏览器都有一个自己最小的等待时间和反应时间(Chrome:5~6ms IE:10~13ms),所以写 0 还是异步编程
  5. console.log(n);
  6. //=> 0 1

题目五:

  1. setTimeout(()=>{
  2. console.log(1);
  3. }, 20);
  4. console.log(2);
  5. setTimeout(()=>{
  6. console.log(3);
  7. }, 10);
  8. console.log(4);
  9. for (let i = 0; i < 9000; i++) {
  10. }
  11. console.log(5);
  12. setTimeout(()=>{
  13. console.log(6);
  14. }, 8);
  15. console.log(7);
  16. setTimeout(()=>{
  17. console.log(8);
  18. }, 15);
  19. console.log(9);
  20. //=> Chrome: 2 4 5 7 9 6 3 8 1
  21. //=> IE: 2 4 5 7 9 1 6 3 8