javascript 堆栈_javascript调用堆栈和事件循环如何工作

javascript 堆栈

Have you ever logged into a website like Facebook and wondered why the page is loaded before all the recent posts?

您是否曾经登录过Facebook这样的网站,并想知道为什么在所有最新帖子之前都加载了该页面?

Have you ever wondered why when you are trying to view things you want to buy on Amazon, you see other components before the items you are interested to buy?

您是否曾经想过,为什么当您尝试查看要在亚马逊上购买的商品时,会在要购买的商品之前看到其他组件?

To understand this, let’s understand how operations are handled from a synchronous and an asynchronous point of view.

为了理解这一点,让我们从同步和异步的角度来理解如何处理操作。

Javascript is synchronous by nature. It means it runs a series of instructions one at a time. If the first instruction has not finished executing, the next line of instruction would not be executed until the first instruction is finished.

JavaScript本质上是同步的。 这意味着它一次运行一系列指令。 如果第一条指令尚未完成执行,则直到第一条指令完成后,下一行指令才会执行。

Let’s take the following code as an example:

让我们以以下代码为例:

const a = 1;
let b = 2;
b = 3;
const c = a + b;

If you run the following javascript code here’s how the call stack would look like:

如果您运行以下javascript代码,则调用堆栈如下所示:

Image for post

It adds each one of those instructions and run each one of them one at a time.

它添加了这些指令中的每一个,并一次运行其中的每一个。

How about functions? When we call functions that have their set of statements how does it affect the call stack?

功能如何? 当我们调用具有其语句集的函数时,它将如何影响调用堆栈?

Let’s take a look at the following example:

让我们看下面的例子:

function mult(a,b){
  return a * b;
}


func multTwo(a, b){
  return 2 * mult(a,b);
}


multTwo(2,3);

Right here, we call multTwo, which calls mult of a and b and multiply it by 2. Notice a pattern here? It calls one after the other but the latest call on the stack will always be executed first.

就在这里,我们叫multTwo,它叫a和b的mult并乘以2。注意这里的模式吗? 它一个接一个地调用,但是堆栈上的最新调用将始终首先执行。

Here’s how the call stack would look like:

调用堆栈如下所示:

Image for post

multTwo gets called, which triggers the mult function call. 2 times 3 evaluates to 6, popping the top of the stack. Since mult(2*3) turns into 6, 2 * 6 turns into 12, popping another element on the stack. At last, multTwo(2,3) then gets evaluated.

调用multTwo,从而触发对mult函数的调用。 2 3的结果为6,弹出堆栈顶部。 由于mult(2 * 3)变成6,所以2 * 6变成12,因此将另一个元素弹出堆栈。 最后,然后对multTwo(2,3)求值。

Now one important question comes up:

现在出现一个重要问题:

If everything is running line by line, how come we still hear about concepts such as promises, asynchronous calls, etc?

如果一切都在逐行进行,那么我们如何还能听到有关诸如Promise,异步调用等概念的信息呢?

That’s because there is a way to perform asynchronous operations with javascript.

那是因为有一种方法可以使用javascript执行异步操作。

Imagine going on your Facebook page and you are scrolling up and down. In a few seconds, you will see new posts coming up as there are more recent posts available.

想象一下,进入您的Facebook页面,您正在上下滚动。 几秒钟后,您会看到新的帖子,因为有更多最新的帖子可供使用。

If browsers are running on javascript and javascript is synchronous by nature, does that mean the browser either cannot be scrolled up and down when the browser is trying to fetch recent posts, etc?

如果浏览器在javascript上运行并且javascript本质上是同步的,这是否意味着当浏览器尝试获取最新帖子等时,浏览器无法上下滚动?

进入事件循环。 (Enter the event loop.)

In javascript, when an asynchronous operation is made, the operation gets put into the event loop instead. Once all the operations are popped from the call stack, then the operations in the event loop get popped(some might be earlier, some might be later depending if they are set on a timeout or if they have returned from a call to get some API data).

在javascript中,当执行异步操作时,该操作将被放入事件循环中。 一旦所有操作都从调用堆栈中弹出,事件循环中的操作就会被弹出(某些操作可能更早一些,某些操作可能会稍晚一些,具体取决于是否将它们设置为超时或是否已从调用中返回以获取一些API数据)。

Here is an example of some javascript asynchronous operations & synchronous operations:

这是一些JavaScript异步操作和同步操作的示例:

const a = 1;
const b = 2;
const c = a + b;


function doSomething(){
  console.log("hi");
}


setTimeout(() => {
  doSomething();
}, 10);


console.log('c: ' + c);

Let’s say we don’t know how the event cycle in javascript works. We probably expect all of the code to run in order. However, if you run this code you will see the following output in this order:

假设我们不知道JavaScript中的事件循环如何工作。 我们可能希望所有代码都能按顺序运行。 但是,如果运行此代码,您将按以下顺序看到以下输出:

  • c: 3

    c:3
  • hi

    你好

Wait, what? Didn’t we call doSomething before we print out the value of c? To understand exactly why this is happening, we have to understand how javascript handles asynchronous operations.

等一下在打印出c的值之前,我们不是叫doSomething吗? 要确切了解这种情况的发生原因,我们必须了解javascript如何处理异步操作。

Let’s take at the following diagram to see what actually to the javascript call stack and event loop on the example above:

让我们看下图,看看上面示例中的javascript调用栈和事件循环实际上是什么:

Image for post

After the first three lines of statements, each line gets ran once, one at a time, with each call being put into the call stack and popped immediately. After these statements, the call stack is empty and the heap contains the value of a, b, and c.

在语句的前三行之后,每一行运行一次,一次运行一次,每个调用被放入调用堆栈并立即弹出。 这些语句之后,调用堆栈为空,并且堆包含a,b和c的值。

Let’s see what happens when the setTimeout statement and the console log statement is called:

让我们看看调用setTimeout语句和控制台日志语句时会发生什么:

Image for post

When setTimeout is called, javascript quickly recognizes it as a web API called and pushes to the stack there. One key point to remember is any web API calls won’t be called until the call stack is empty. Because of that, console.log actually gets pushed into the call stack and gets popped first, triggering the console.log call.

调用setTimeout时,javascript会Swift将其识别为已调用的Web API,并推送到该处的堆栈。 要记住的关键一点是,在调用堆栈为空之前,不会调用任何Web API调用。 因此,console.log实际上被推入调用堆栈并首先弹出,从而触发console.log调用。

Once the setTimeout timer expires, the callback of setTimeout is getting pushed into the call stack. Because doSomething calls console.log, now console.log gets pushed into the call stack.Console.log then gets popped off the stack and gets called and then doSomething gets popped off the stack.

一旦setTimeout计时器到期,则setTimeout的回调将被推入调用堆栈。 因为doSomething调用console.log,所以console.log现在被推送到调用堆栈中.Console.log然后被弹出堆栈并被调用,然后doSomething被弹出堆栈。

Wow, there is a lot going on right?

哇,有很多事要发生吗?

To understand how javascript really operates, remember the few following concepts:

要了解javascript的实际运行方式,请记住以下几个概念:

  • javascript is synchronous by nature. It runs line by line, push each item into a call stack, and popping them off immediately to run each call.

    javascript本质上是同步的。 它逐行运行,将每个项目压入一个调用堆栈,并立即弹出它们以运行每个调用。
  • If it calls a function, it pushes the function call to the call stack and then the inner function calls into the call stack. The inner function call gets popped off the stack and triggered first before the main function call.

    如果调用函数,则将函数调用推入调用堆栈,然后将内部函数调用推入调用堆栈。 内部函数调用从堆栈中弹出,并在主函数调用之前首先触发。
  • Asynchronous calls are put into the event loop instead of the call stack. Every operation in the call stack must be run before event loop operations are triggered, regardless of when these asynchronous calls received feedback (can be a success or fail response).

    异步调用被放入事件循环中,而不是调用堆栈中。 无论这些异步调用何时收到反馈(可以是成功或失败响应),都必须在调用事件循环操作之前运行调用堆栈中的每个操作。

Feel free to comment or ask any questions if there are any.

如有任何疑问,请随时发表评论或提出任何问题。

Can you think of how many synchronous vs asynchronous calls are currently running in this article as you read through it?

阅读本文时,您能想到当前正在运行多少个同步调用与异步调用吗?

Happy coding. Cheers.

快乐的编码。 干杯。

翻译自: https://medium.com/weekly-webtips/how-javascript-call-stack-and-event-loop-works-da9077c56a8b

javascript 堆栈

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值