Placeholder Image

字幕列表 影片播放

  • >> (Phillip Roberts) hello, come in and sit down.

    (Phillip Roberts))大家好,請進、請坐

  • So for the last session before the afternoon break, we have Phillip Roberts who works at

    所以在下午休息時間之前的最後一節時間 我們邀請到Phillip Roberts

  • Andea and is here from London ‑‑ Scotland.

    他任職於&yet公司,並從倫敦...是蘇格蘭

  • Edinbrough.

    愛丁堡過來的

  •  ‑‑ wow, ten second memory, he's going to talk about the vent loop.

    哇,才一下就忘了 他接下來會來談談Event Loop

  • If everyone could give Phillip a big brownedder round of applause.

    請大家給Phillip掌聲歡迎他

  • >> Phillip Roberts: Okay hello everyone, thanks for coming to the side track, it's awesome

    Phillip Roberts: 大家好,謝謝大家前來這個小場次 能看到這裡有滿滿的人

  • to see it packed out in here.

    感覺非常棒

  • Can everyone give me a stretch.

    現在能請大家做個伸展動作嗎?

  • I needed to stretch, so I look less weird.

    因為我需要伸展一下,這樣我看起來才不會奇怪

  • I want to talk about the event loop and what the heck is the event loop, as in the event

    我想要談一下Event Loop(事件循環) JavaScript裡面的Event Loop

  • loop inside JavaScript.

    Event Loop到底是什麼東西

  • So first up, as he said I work for AndYet which is an awesome little Dev shop in the

    首先,我說過我任職於&yet公司 我們是間小型而出色的美國公司

  • US, look us up if you need help with realtime stuff.

    如果有人需要即時性事情的幫忙 歡迎查一下我們的資訊

  • That's what we're good at.

    那是我們的專業

  • So, about 18 months ago--I'm a paid professional JavaScript developer--I thought to myself

    所以呢,大約18個月之前,我是個JavaScript工程師 我在心中想著

  • how does, like JavaScript actually work?

    JavaScript到底是怎麼樣運作的呢?

  • And I wasn't entirely sure.

    我當時並不是完全肯定

  • I'd heard V8 as a term, chrome's Runtime didn't really know what that meant, what that did.

    當時我有聽過V8引擎、chrome的Runtime這些詞 但不清楚是什麼意思,或是有什麼功能

  • I'd heard things like single threaded, you know obviously I'm using callbacks.

    我聽過一些東西,像是Single Thread(單執行緒) 我很明顯是在用Callback(回調)

  • How do callbacks work?

    Callback是怎麼運作的?

  • I started a journey of like reading and research and experimenting in the browser which basically

    於是我開啟了一段閱讀、研究 和在瀏覽器上的實驗的過程

  • started like this.

    一開始是長這樣子的

  •  ‑‑ I was kind of like JavaScript what are you.

    我那時心裡有點在想:“JavaScript,你是什麼鬼啊?”

  • I'm a single threaded single concurrent language ‑‑ right.

    然後它回我說:“我是個單執行緒的程式語言” ...好喔

  • yeah, cool, I have a call stack, an event loop, a callback queue, and some other APIs

    好,我有一個Call stack(呼叫堆疊)、一個Event Loop(事件循環) 一個Callback queue(回調佇列),還有一些API

  • and stuff.

    等等的東西

  •  ‑‑ rite.

  • I did not do a computer science degree.

    我沒有念過電腦科學學位

  • I mean, these words, they're words, so I heard about V8 and the various Runtimes and different

    我是說,這些名詞的意義我不懂,所以我聽過V8引擎 還有幾個Runtime函式,還有不同的瀏覽器

  • browsers so I looked to V8 do you have a call stack, an event loop, a callback queue, and

    所以我看了V8引擎,問說:你有沒有呼叫堆疊 事件循環、回調佇列...

  • some other APIs and stuff, I have a call stack and a heap, I don't know what those other

    還有其他API等等的...我有呼叫堆疊,還有堆積 我不知道其他的東西是什麼

  • things are, okay, interesting so basically 18 months passed.

    好,很有意思...於是18個月基本上就過去了

  • And I think I get this.

    然後我覺得我搞懂了

  • (Laughing) and so, this is what I want to share with you today.

    (笑聲)所以,這就是我今天想和大家分享的內容

  • Hopefully this will be useful if you're relatively new to JavaScript, help you understand why

    如果你是JavaScript的新手的話 希望這些對你有幫助,幫助你了解

  • JavaScript is so weird when you compare it to other languages you might used why callbacks

    為何JavaScript和其他你可能用過的程式語言 相比這麼古怪,為什麼回調

  • are a thing, cause us hell but are required.

    是重要的東西,造成我們一堆痛苦 但是又躲不掉

  • And if you're an experienced JavaScript developer hopefully give you some fresh insights how

    如果你是一位經驗豐富的JavaScript開發人員 那我希望可以給你一些關於

  • the Runtime you're using works so you can think about it a little better.

    Runtime是如何運行的新見解 讓你能夠多深入思考一下

  • So if we look at the JavaScript Runtime itself like V8 which is the Runtime inside Chrome.

    所以,我們可以看一下JavaScript Runtime V8引擎就是Chrome中的Runtime

  • This is a simplified view of what JavaScript Runtime is.

    這個是JavaScript Runtime的簡化示意圖

  • The heap, where memory allocation happens, and then there's the call stack, which is

    Heap記憶體,就是進行記憶體分配的地方 然後是呼叫堆疊,這個是

  • where your stack frames are and all that kind of stuff, but, if you, like, clone the V8

    堆疊框架,還有所有相關的東西所在的位置 不過,如果比如說你複製V8引擎的程式碼庫

  • code base and grep for things like setTimeout or DOM or HTTP request, they're not in there,

    然後用grep抓取一些像是setTimeout 或是DOM或是HTTP請求的東西,那些並不在那裡

  • they don't exist in V8, which was a surprise to me.

    那些並不在V8引擎裡 這件事讓我大吃一驚,對吧?

  • It's first thing you use when you start thinking about async stuff and it's not in the V8 source.

    setTimeout有點像是用JavaScript、想到非同步時 會用的第一樣東西,而那竟然不在V8引擎裡

  • Hmm ... interesting.

    嗯...很有意思

  • So, over this 18 months of discovery I come to realize this is really, this is really

    因此,在經過這18個月的發現之中 我逐漸了解到這確實是

  • the bigger picture, this is what I'm hoping to get you on board with today and understand

    更大的概念,這就是我今天希望 帶大家認識的東西,了解一下

  • what these pieces are, we have the V8 Runtime but then we have these things called web APIs

    這些東西是什麼,我們有V8引擎的Runtime 但是我們也有叫做Web API的東西

  • which are extra things that the browser provides.

    而Web API是瀏覽器所提供的額外的東西

  • DOM, AJAX, time out, things like that, we have this mythical event loop and the callback

    像是DOM、AJAX、setTimeout之類的東西 然後我們還有神秘的Event Loop,以及...

  • queue.

    callback queue(回調佇列)

  • I'm sure you've heard some of these terms before, but maybe you don't quite understand

    我很確定大家都聽過一部分的專有名詞了 但也許並不是太理解

  • how these pieces pull together.

    這些東西是如何拼湊在一起的

  • So, I'm going to start from the beginning, some of this will be new, to words might be

    所以,我要從頭開始講起 有些字詞對於一部分人可能很陌生

  • new to people, other people will get this.

    一部分人可能聽得懂

  • We're going to quickly move on from here, bear with me if this is obvious, I think for

    不過我們要開始快速講下去 如果太簡單的話,請忍耐一下,但我認為

  • a lot of people it's not.

    對大多數人來說並不簡單

  • So, JavaScript is a single threaded programming language, single threaded Runtime, it has

    所以呢,JavaScript是一種單執行緒的程式語言 單執行緒的Runtime

  • a single call stack.

    它有單執行緒的呼叫堆疊

  • And it can do one thing at a time, that's what a single thread means, the program can

    它可以一次做一件事 那就是單執行緒的意思,程式一次

  • run one piece of code at a time.

    可以跑一段程式碼

  • So, let's try and visualize that just to get our heads around what that mean, so if I have

    所以,我們來試著將它視覺化 來幫助我們為了解它的意思,所以如果我有

  • some code like this on your left, we've got a few functions, a function multiplier which

    一些左手邊的程式碼 這裡有一些函式,有乘法函式

  • multiplies two numbers, square which calls multiply with the same number twice, a function

    能將兩個數字相乘 平方函式,把同一個數字乘以兩次

  • which prints the square of a number of calling square and then calling console.log and then

    有個函式是如果我要平方功能,然後呼叫console.org 它就將一個數字的平方結果印出來

  • at the bottom of our file we actually run print square, this code all good?

    然後在我們檔案的底下,我們執行了printSquare 這段程式大家都懂嗎?

  • Make sense?

    合理嗎?

  • Cool.

  • So, if we run this, well, I should back up a step, so the call stack is basically ‑‑

    所以,如果我們執行它,等等,我應該倒回一步 抱歉,所以Callstack基本上

  • it's a data structure which records basically where in the program we are, if we step into

    是一種資料結構,它能夠記錄幾種情況下 我們在程式中的哪個位置,比如說進入

  • a function, we put something on to the stack, if we return from a function, we pop off the

    一段函式、比如我們在stack(堆疊)上放某個東西 從函式回傳結果的時候、我們取下stack頂端的東西

  • top of the stack that's all the stack can do, ‑‑ so if you run this file, there's

    那些就是stack能做的事情... 所以如果你執行這個檔案

  • kind of a main function, right, like the file itself, so, we push that on to the stack.

    裡頭有個主函式,對吧,就像這個檔案本身 所以我們把這個放到堆疊上

  • Then we have some function definitions, they're just like defining the state of the world,

    接著還有一些函式定義 就像是定義了整個世界的狀態

  • and finally we got to print square, right, so print square is a function call, so we

    最後還有printSquare函式 printSquare是一種函式呼叫方式

  • push that on to the stack, and immediately inside print square, push on to the stack,

    所以我們把它推到堆疊上 然後在printSquare裡面,推到堆疊上的

  • which calls multiply, now we have a return statement, we multiply A and B and we return,

    再呼叫Multiplt,現在我們有一個return statement(回傳陳述) 我們會把A和B相乘,然後回傳

  • when we return we pop something off the stack, so, pop, multiplier of the stack, returning

    回傳的時候,我們會把某個東西從stack上移除 所以,我們移除相乘指令,回到square

  • to square, return to print square, console.log, there's no return, it's implicit, because

    回到printSquare、console.org 現在是printSquare、沒有回傳指令,這是隱含的

  • we got to the end of the function, and we're done so that's like a visualization of the

    因為我們已經走到函式的盡頭,這樣就走完了 所以這就是呼叫堆疊的示意圖

  • call stalk, does that make sense?

    這部分可以理解嗎?

  • (Yes, Phil) even if you haven't thought about the call stack before, you've come across

    (可以,Phil)就算你以前沒有想到過呼叫堆疊 你也一定有碰過

  • it when you've been doing browserside development, so if we have code like this, a function baz

    那就是當你在瀏覽器端做開發的時候 所以假設我們有個這樣的程式,一個名為baz的函式

  • which calls bar, which calls Foo, which throws an error if we run it in Chrome we see this.

    呼叫bar函式,而bar函式又呼叫Foo函式,最後丟出錯誤訊息 如果在Chrome上執行,我們會在Dev Tools看到這個...未被捕捉的錯誤:Oops

  • And it prints the stack trace, right, the state of the stack when that error happened,

    程式會印出堆疊追蹤記錄,對吧? 在錯誤發生時,堆疊的狀態

  • so, uncaught error oops Foo, bar, Baz, anonymous function, which is our main.

    所以我們看到:未被捕捉的錯誤: Oops Foo、bar、Baz、匿名函式,也就是我們的主程式

  • Equally, if you've heard the term like blowing the stack, this is an example of that.

    同樣地,如果你有聽過一些像是堆疊爆炸 的名詞的話,這就是其中一個例子

  • Have a function foo which calls Foo , so what's going to happen ? We have a function main

    foo函式呼叫foo函式的話,會怎麼樣? 這個嘛...我們跑主程式

  • which calls foo which calls foo, which calls foo, which calls foo, and ultimately chrome

    呼叫foo函式,它再去呼叫foo函式 然後再呼叫foo函式,然後再呼叫foo函式,到最後chrome會說

  • says, you probably didn't mean to call foo 16,000 times recursively, I'll just kill things

    你可能不是真的要重複呼叫foo函式一萬六千次 所以我會幫你中止一些

  • for you and you can figure out where your bug lies, right.

    然後你就能釐清bug在哪裡了,對吧

  • So although I may be representing a new side of the call stack you have some sense of it

    雖然我可能是在呈現呼叫堆疊的新的一面 你們可能多少已經在

  • in your development practice already.

    開發的實作過程中多少了解一些了

  • So, the big question then comes is like what happens when things are slow?

    所以,接著浮現的大哉問是 程式執行速度緩慢時會怎麼樣?

  • So, we talk about blocking and blocking behavior and blocking, there's no strict definition

    我們會講到“阻塞”,還有阻塞的行為 阻塞其實沒有一個嚴格的定義

  • of what is and didn't blocking, really it's just code that's slow.

    來說明什麼是阻塞、又什麼不是 它其實只是一段很慢的程式

  • So console.log isn't slow, doing a while loop from one to ten billion is slow, network requests

    所以說console.org並不慢 執行一段一到一百億的while迴圈有點慢

  • are slow.

    網路請求很慢

  • Image requests are slow.

    圖片請求很慢

  • Things which are slow and on that stack are what are blocking means.

    跑起來很慢、同時又在該堆疊上的東西 就是阻塞的意思

  • So heres a little example, so let's say we have, this is like a fake bit of code, getSynchronous,

    這裡有個小例子,假設我們 弄一串假的程式碼:getSynchronous

  • right, like jQuery is like, AJAX request.

    就好比jQuery...AJAX請求

  • What would happen if those were synchronous requests, forget what we know about async

    如果這些是同步請求的話,會怎麼樣? 先忘掉非同步回調這件事

  • callbacks they're synchronous.

    都先當作同步就好

  • If we go through it like we have, we call getSync and then we wait, because then we're

    如果瀏覽一下我們走過了哪些東西 我們呼叫了getSync,然後我們等了一下,因為後來

  • doing network request, network is relative to computers, are slow, hopefully that network

    我們在做網路請求 網路相對於電腦是很慢的,希望那段網路請求

  • requests completes, we can move on, wait, move on.

    已經完成了,然後我們就能繼續跑... 等待、繼續跑...

  • Wait, and, I mean, this network request might never finish, so ... yeah, I guess I'll go

    等待,然後,這段網路請求可能永遠不會跑完 所以...我想我不如

  • home.

    回家好了

  • Finally those three, you know blocking behaviors complete and we can clear the stack, right.

    最後那三個,blocking(阻塞)行為都已經完成 然後我們就能清除stack了,對吧?

  • So in a programming language is single threaded you're not using threads like say Ruby, that's

    所以在一個單執行緒的程式語言中 不能像Ruby般使用多個執行緒

  • what happens, right, we make a network request, we have to just wait till it's done, because

    就是那樣子,對吧,我們做了一個網路請求 我們只能等到它跑完為止

  • we have no way of handling that.

    因為我們沒有處理這種情況的方法

  • Why is this actually a problem?

    而這點為什麼是個問題呢?

  • The problem is because we're running code in browsers.

    它之所以為問題 是因為我們是在瀏覽器裡執行程式的

  • So, let's you ‑‑ here we go, okay.

    我們來...這裡,好

  • So this is just, this is Chrome, this is the code I just ran.

    這個是Chrome,這裡是我剛剛跑過的程式

  • Browsers don't give us ‑‑ well they do give us synchronous AJAX request, I'm faking

    瀏覽器不會給...噢,它其實會給我們 同步AJAX請求,我現在用一個大while迴圈

  • this out with a big while loop, because it's synchronous, I basically while loop for five

    來假裝做到這件事,因為while 迴圈是同步的 我基本上會在繼續跑下去之前

  • seconds before continuing, so if I open up the console here.

    先做五秒的while迴圈,所以如果我在這裡打開console

  • We can see what happens, so with request foo.com, why this is happening, I can't do anything,

    我們就能看到發生了什麼事,所以我們對foo.com 提出請求,所以我們會想:怎麼會這樣?我什麼都做不了

  • right, even the run button hasn't finished rerendering the fact that I clicked it.

    就算是“執行”按鈕 即使我剛剛按過也沒未rerender(重新渲染)完成

  • The browser is blocked, it's stuck, it can't do anything until those requests complete.

    因為瀏覽器這時候被阻塞了,卡住了 直到請求都完成之前,它什麼都做不了

  • And then all hell breaks loose because I did some stuff,it figured that out I'd done it,

    然後整個死結都打開了 因為我做了一些事,它發現我已經完成了

  • it couldn't actually render it.

    它只是不能呈現結果

  • Couldn't do anything.

    什麼都不能做

  • That's because if that call stack has things on it, and here it's got these yeah, it's

    這是因為如果那段Call Stack上有東西的話 而這邊有...對...

  • still going.

    它還在跑

  • We've got the synchronous request, the browser can't do anything else.

    我們現在有同步請求 那瀏覽器其他事就做不了了

  • It can't render, it can't run any other code, it's stuck.

    它無法顯示畫面、無法跑其他程式碼,都卡住了

  • Not ideal, right if we want people to have nice fluid UIs, we can't block the stack.

    情況並不理想,對吧?如果我們希望人們 能看到流暢的 UI,我們就不能阻塞Stack

  • So, how do we handle this?

    那我們要怎麼處理呢?

  • Well the simplest solution we're provided with is asynchronous callbacks, there's almost

    這個嘛...我們所能用到的 最簡單的解法就是Async Callback(非同步回調)

  • no blocking functions in the browser, equally in node, they're all made asynchronous, which

    瀏覽器中幾乎沒有Blocking(阻塞式)函式 在Node裡也是一樣,都是Async(非同步)的

  • basically means we run some code, give it a callback, and run that later, if you've

    這基本上表示我們執行一些程式碼 給它回調,然後再執行,如果你已經

  • seen JavaScript you've seen asynchronous callbacks, what does this actually look like.

    看過JavaScript,你就有看過非同步回調 它實際上是什麼樣的呢?

  • Simple example to remind people where we're at.

    這裡有個簡單的例子 來提醒大家我們的問題在哪

  • Code like this, console.log hi.

    像這樣的程式碼,console.log('Hi')

  • Write, we run the setTimeout, but that queue's the console log for future so we skip on to

    我們執行setTimeout函式,但是那段佇列 不知為何是之後會出現的console.log,所以我們直接

  • JSConf and then five seconds later we log "there" right, make sense?

    跳到JSConfEU,然後五秒鐘後 我們就紀錄了“there”,對嗎?

  • Happy.

    行嗎?

  • Basically that's setTimeout is doing something.

    基本上,那個setTimeout函式正在做事

  • So, asynchronous callbacks with regards to the stacks we saw before ... how does this

    所以,我們之前看過的堆疊的 這一方面的非同步回調來說...是怎麼

  • work?

    運作的呢?

  • Let's run the code.

    那麼,我們就來跑程式吧

  • Console.log hi. setTimeout.

    console.log('Hi')、setTimeout函式 好,接下來會怎麼樣?

  • We know it doesn't run immediately, we know it's going to run in five seconds time, we

    我們都知道它沒有立刻執行 我們知道它要五秒鐘後才會跑

  • can't push it on to the stack, somehow it just disappears, we don't have like a way

    我們無法把它推到堆疊上 不知為何地它就消失了,我們還沒有方法

  • of describing this yet, but we'll come to it.

    去描述這件事,但是等一下會再講回來

  • We log JSConfEU, clear, five seconds later somehow magically "there" appears on the stack.

    我們打印JSConfEU、清除 五秒鐘後,不知為何,“there”就神奇地出現在Stack上了。

  • How does that happen?

    這是怎麼回事?

  • And that's ‑‑ this is basically where the event loop comes in on concurrency.

    這基本上就是是事件循環 在並發執行上會發揮作用的地方

  • Right, so I've been kind of partially lying do you and telling you that JavaScript can

    好,所以我一直算是沒講出完整的事實 告訴你們JavaScript只能

  • only do one thing at one time.

    一次做一件事情

  • That's true the JavaScript Runtime can only do one thing at one time.

    沒有錯,JavaScript Runtime 一次只能做一件事

  • It can't make an AJAX request while you're doing other code.

    你在進行其他程式的時候 它就無法做出AJAX的請求