Javascript is required
JavaScript管理任务

image-20210507225104719

是什么

JavaScript是单线程的:一次只能运行一个任务。通常这没什么大不了的,但是现在想象您正在运行一个耗时30秒的任务。是的。在此任务中,我们等待30秒才能进行其他任何操作(默认情况下,JavaScript在浏览器的主线程上运行,因此整个用户界面都卡住了))

浏览器为我们提供了JavaScript引擎本身不提供的一些功能:Web API。这包括DOM API,setTimeoutHTTP请求等。这可以帮助我们创建一些异步的,非阻塞的行为

image-20210507225359101

同步任务的执行会阻塞主线程。

为什么

为了让用户获得更好的交互体验,为了避免单线程的任务执行过程中发生阻塞,出现了事件循环( Event Loop)机制


JavaScript 解释器会以栈的方式管理这些执行上下文、以及函数之间的调用关系,形成函数调用栈(call stack)(调用栈可理解为一个存储函数调用的栈结构,遵循 FILO(先进后出)的原则

image-20210507225541288

respond函数返回一个setTimeout函数。在setTimeout由Web API提供给我们延事任务,而不会阻塞主线程。我们传递给该setTimeout函数的回调函数,箭头函数已添加到Web API。同时,该setTimeout函数和response函数从堆栈中弹出,它们都返回了它们的值!

在Web API中,计时器的运行时间与我们传递给它的第二个参数1000ms一样长。回调不会立即添加到调用堆栈中,而是会传递给称为回调队列的东西。

这并不意味着在1000毫秒后将回调函数添加到调用堆栈中(从而返回一个值)!它只是在1000毫秒后添加到队列中。但这是一个队列,该函数必须等待轮到它!

将队列与调用堆栈连接起来!如果调用堆栈为,那么如果所有先前调用的函数都返回了它们的值并已从堆栈中弹出,则队列中的第一项将添加到调用堆栈中。在这种情况下,没有其他函数被调用,这意味着当回调函数成为队列中的第一项时,调用堆栈为空。

image-20210507225914027

回调被添加到调用堆栈中,被调用,并返回一个值,并从堆栈中弹出。

例子

const foo = () => console.log("First");
const bar = () => setTimeout(() => console.log("Second"), 500);
const baz = () => console.log("Third");

bar();
foo();
baz();

宏任务和微任务

image-20210507230237738

image-20210507230346031

Promises

Promise解析和调用它then()catch()或者finally(),方法,该方法中的回调被添加到microtask队列!这意味着,在回调then()catch()finally()方法不立即执行,实质上增加了一些异步行为

1. 当前在调用堆栈中的所有函数都将执行。当它们返回一个值时,它们会从堆栈中弹出
2. 当调用堆栈为空时,所有排队的微任务都一一弹出到调用堆栈上,然后执行!(微任务本身也可以返回新的微任务,从而有效地创建了无限的微任务循环
3.如果调用堆栈和微任务队列都为空,则事件循环将检查(宏)任务队列上是否还有任务。任务被弹出到调用堆栈上,执行并弹出!

参考

https://dev.to/lydiahallie

前端进击笔记