何为同步异步

同步任务(synchronous

  1. 同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
  2. 同步任务进栈顺序:先进后出,后进先出;(栈只有一端开口);
  3. 同步会阻塞程序的执行;

同步任务:页面的初始化、DOM 操作、计算任务;

大白话:同步就是我强依赖于你(对方),我必须等到你的回复,才能去做下一步的事情。

异步任务(asynchronous

  1. 不进入主线程,而进入任务队列的任务,只有等主线程任务执行完毕,任务队列开始通知主线程,请求执行任务,该任务才会进入主线程执行。
  2. 异步任务进任务队列顺序:先进先出,后进后出;(队列有两端开口);
  3. 异步不会阻塞程序的执行;

异步任务: 网络请求、定时器、事件处理、异步函数;

大白话:异步就是我并不强依赖于你,我对你是否回不回复我的信息并不在意,无论你回不回复我,我都会继续去做我的事情。

一、JavaScript是一门单线程语言

总所周知,JavaScript是一门单线程语言。单线程是指JavaScript引擎执行JavaScript时只分了一个线程给它执行,所以说执行JavaScript时是单线程的。

二、何为进程?何为线程?

进程:

进程是指在计算机系统中正在执行的一个程序实例。一个程序可以创建一个或多个进程(例如:打开一个浏览器,在浏览器上打开多个网页),每个进程都有自己的内存空间、执行状态和资源使用情况。进程是操作系统对程序的一次动态执行过程的抽象。

多进程示例:

  1. 浏览器是多进程
  2. 不同类型的标签页都会开启一个新的进程
  3. 相同类型的标签页是会合并到一个进程

线程:

线程是CPU调度的最小单位,是建立在进程的基础上运行的单位,共享进程的内存空间。(CPU是电脑的大脑,可以同时打开多个程序(也可以抽象地理解为软件),例如:QQ、微信,一个线程分配给QQ,一个给微信)

三、单线程意味着什么?

JavaScript 同时只能执行一个任务,其他任务都必须在后面排队等待。也就是说代码只能同步执行,必须执行上一行才能执行下一行。然而并不是还有异步

四、微任务与宏任务

同步、异步-LMLPHP

微任务(microtask)

  1. 微任务会在当前任务执行完成后立即执行,在浏览器渲染之前执行。
  2. 微任务具有较高的优先级,在每个事件循环中会在宏任务执行之前执行。

微任务:Promise async/await 、Object.observe MutationObserver、 process.nextTick(Node.js 环境)。

宏任务(macrotask)

  1. 宏任务会在事件循环中执行,一般来自外部的事件,如定时器事件、UI交互事件和网络请求事件等。

宏任务setTimeout、setInterval、Ajax、DOM事件 、script(整体代码) 、I/O、UI交互事件、setImmediate(Node.js 环境)。

总结

[ 宏任务、微任务 ]是指JavaScript中异步任务的两种不同任务的分类,宏任务类似于整体的异步任务,微任务则是宏任务中的一个子任务。

  • 宏任务表示需要异步执行的任务
  • 微任务表示宏任务执行后需要立即执行的子任务

如下图所示:微任务优先级 > 宏任务优先级

同步、异步-LMLPHP

五、事件循环(Event Loop)又被称为事件轮询

同步、异步-LMLPHP

JavaScript的异步编程通过执行栈和消息队列来实现。首先所有的同步任务都是在主线程上执行的,它会形成一个执行栈,异步任务不会在主线程上执行,当异步任务得到响应(如某个点击事件、服务加载完成、setTimeout等待时间截止)就会被推入消息队列中。当执行栈里面的任务执行完的时候(栈空),JS引擎就会去消息队列中读取任务,它会把这个任务中的回调函数压入执行栈中,然后执行栈就又开始新的同步任务执行。


这种执行栈空就去消息队列读取任务的过程时不断循环的,每次栈空都会去消息队列读取任务,如果没有任务就一直等待,知道有新的任务出现,这叫做事件循环(event Loop)。

六、练习题

// 第一题
console.log("开始");

setTimeout(function() {
  console.log("定时器回调函数");
}, 0);

console.log("结束");



// 第二题
console.log("开始");

setTimeout(function() {
  console.log("定时器回调函数");
}, 0);

Promise.resolve().then(function() {
  console.log("微任务");
});

console.log("结束");



// 第三题
console.log("开始");

setTimeout(function() {
  console.log("定时器回调函数");
}, 0);

Promise.resolve().then(function() {
  console.log("微任务1");
}).then(function() {
    console.log("微任务2");
});

console.log("结束");



// 第四题
console.log("开始");

setTimeout(function() {
  console.log("定时器回调函数");
}, 0);

Promise.resolve().then(function() {
  console.log("微任务1");
  Promise.resolve().then(function() {
    console.log("微任务2");
  });
});

console.log("结束");



// 第五题
console.log("开始");

setTimeout(function() {
  console.log("定时器回调函数1");
  Promise.resolve().then(function() {
    console.log("嵌套微任务1");
  });
}, 0);

setTimeout(function() {
  console.log("定时器回调函数2");
}, 0);

Promise.resolve().then(function() {
  console.log("微任务");
});

console.log("结束");



// 第六题
console.log('script start');

setTimeout(function() {
  console.log('setTimeout');
}, 0);

Promise.resolve().then(function() {
  console.log('promise1');
}).then(function() {
  console.log('promise2');
});

console.log('script end');


// 第七题
console.log('script start');

setTimeout(function() {
  console.log('setTimeout1');
}, 0);

Promise.resolve().then(function() {
  console.log('promise1');
}).then(function() {
  console.log('promise2');
});

setTimeout(function() {
  console.log('setTimeout2');
}, 0);

console.log('script end');



// 第八题
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');


09-30 19:12