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的請求

  • It can't do a setTimeout while you're doing another code.

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

  • The reason we can do things concurrently is that the browser is more than just the Runtime.

    而我們能夠同時做事的原因是 瀏覽器不只有Runtime而已

  • So, remember this diagram, the JavaScript Runtime can do one thing at a time, but the

    所以,把這張圖記起來 JavaScript Runtime一次只能做一件事

  • browser gives us these other things, gives us these we shall APIs, these are effectively

    但是瀏覽器會提供我們其他東西 這些都是你無法取得的執行緒

  • threads, you can just make calls to, and those pieces of the browser are aware of this concurrency

    你只能呼叫它們 而瀏覽器知道一點,同步並發這時候

  • kicks in.

    就發揮作用了

  • If you're back end person this diagram looks basically identical for node, instead of web

    如果你是個後端工程師 那麼這張圖表和Node基本相同

  • APIs we have C++ APIs and the threading is being hidden from you by C++.

    我們使用的其實是C++ API,而不是 WebAPI 而執行緒是讓C++ API從你眼前隱藏起來了

  • Now we have this picture let's see how this code runs in a more full picture of what a

    現在我們有了這張圖片,讓我們看一下這段程式 如何在瀏覽器中運行

  • browser looks like.

    有個更完整的概念

  • So, same as before, run code, console log hi, logs hi to the console, simple.

    所以,和以前一樣,執行程式碼、console.log('Hi') console出現log('Hi'),很簡單

  • now we can see what happens when we call setTimeout.

    現在我們可以看到呼叫setTimeout時會發生什麼

  • We are ‑‑ we pass this callback function and a delay to the setTimeout call.

    我們把這個回調函式和一個延遲時間 丟給setTimeout

  • Now setTimeout is an API provided to us by the browser, it doesn't live in the V8 source,

    現在setTimeout是瀏覽器提供給我們的API 它不在V8引擎中

  • it's extra stuff we get in that we're running the JavaScript run

    那像是我們從環境中額外得到的東西 我們現在就來

  • time in.

    執行JavaScript Runtime

  • The browser kicks off a timer for you.

    瀏覽器為你啟動了一個計時器

  • And now it's going to handle the count down for you, right, so that means our setTimeout

    現在它會為你倒數計時 所以這表示著我們的setTimeout呼叫

  • call, itself is now complete, so we can pop off the stack.

    現在已經完成,因此我們可以從堆疊中移除

  • JSConfEU”, clear, so, now we've got this timer in the web API, which five seconds later

    JSConfEU...清掉了 所以,現在在Web API中有一個計時器,它五秒鐘後

  • is going to complete.

    就會完成工作

  • Now the web API can't just start modifying your code, it can't chuck stuff onto the stack

    現在,Web API不能只是直接修改你的程式碼 它不能在準備就緒時

  • when it's ready if it did it would appear randomly in the middle of your code so this

    就將東西丟到堆疊上,因為如果這樣 它就會隨機出現在你的程式碼之中

  • is where the task queue or callback queue kicks in.

    所以這裡就是任務佇列或回調佇列 發揮作用的地方了

  • Any of the web APIs pushes the callback on to the task queue when it's done.

    基本上,在跑完之後 任何Web API都會將回調推送到任務佇列

  • Finally we get to the event loop, title of the talk, what the heck is the event loop

    最後,我們要談到事件循環,也就是這場演講的主題 事件循環到底是什麼

  • is like the simplest little piece in this whole equation, and it has one very simple

    它就像是這整個方程式當中 最單純的小拼圖,它只有一個非常簡單

  • job.

    的工作

  • The event loops job is to look at the stack and look at the task queue.

    事件循環的工作是查看堆疊 並查看任務佇列

  • If the stack is empty it takes the first thing on the queue and pushes it on to the stack

    如果堆疊是空的,它就會將第一個東西 放到佇列上,並將其堆到堆疊上

  • which effectively run it.

    讓堆疊能有效執行

  • So here we can see that now the stack is clear, there's a callback on the task queue, the

    所以,在這裡我們能看到堆疊已經清空了 任務佇列上有一個回調

  • event loop runs, it says, oh, I get to do something, pushes the callback on to the stack.

    事件循環執行,它說:“噢,我得做些事情 來,把回調推到堆疊上”

  • Remember it's the stack is like JavaScript land, back inside V8, the callback appears

    要記得這個堆疊是JavaScript的領域,對吧 這回到了V8內部,所以呢,回調出現在

  • on the stack, run, console.logthere”, and we're done.

    堆疊上、執行、console.log('there') 然後就完成了

  • Does that make sense?

    可以聽懂嗎?

  • Everyone where me?

    大家都有跟上嗎?

  • Awesome!

    太棒了

  • Okay.

    好的

  • So, now we can see how this works with probably one of the first encounters you would have

    所以,現在我們能看到 在你可能第一次使用非同步工具時

  • had with Async stuff which for some weird reason someone says says you have to call

    這是如何一起運作的,非同步工具 出於某些奇怪的理由,有人說,噢你必須

  • setTimeout zero, ‑‑ okay, you want me to run the function in zero time?

    把setTimeout設定為零 好,你要我在這個函式用時間零來執行嗎?

  • Why would I wrap it in a setTimeout?

    我為什麼要把它包在setTimeout裡呢?

  • Like the first time you run across this, if you're like me,i see it doing something, but

    就像第一次遇到這種情況一樣 如果你跟我一樣,我看得出來它在做些什麼

  • I don't know why.

    但是我不知道為什麼

  • The reason is, generally, if you're trying to defer something until the stack is clear.

    原因是,通常你會嘗試推遲某些任務 直到到堆疊被清空之前,對吧?

  • So we know looking at this, if you've written JavaScript, that we're going to see the same

    因此,現在看到這個,我們就會知道 如果你已經寫好了一段JavaScript,那就會看到相同的結果

  • result, we're going to seehi” “JSConf”, andthereis going to appear at the

    我們會看到Hi、我們會看到JSConfEU 還有there會神奇地出現在

  • end.

    最後

  • We can see how that happens.

    我們可以看到那是怎麼來的

  • The setTimeout zero, now it's going to complete immediately and push it on to the queue, remember

    setTimeout時間設零,現在它很快就要完成 然後會把它推送到佇列

  • what I said about the event loop, it has to wait till the stack is clear before it can

    要記住,我所介紹的關於事件循環的特性 它必須等到堆疊清空後才可以

  • push the callback on to the stack, so your stack is going to continue to run, console.log

    把回調推到堆疊上 所以你的堆疊就能繼續執行console.log

  • hi”, “JSConfEUand clear, now the event loop can kick in and call your callback.

    “Hi”、“JSConfEU”,然後清空 現在事件循環就能夠啟動、呼叫你的回調了

  • That's like an example of setTimeout zero, is deferring that execution of code, for whatever

    就像setTimeout時間設零的例子一樣 無論原因,都把程式碼的執行

  • reason to the end of the stack.

    推遲到堆疊的最後

  • Or until stack is clear.

    或是直到堆疊清空為止

  • Okay.

  • So, all these web APIs work the same way, if we have AJAX request, we make an AJAX request

    所以,所有的這些Web API都以相同的方式運作 如果有AJAX請求,我們就發出AJAX請求

  • to the URL with a callback, works the same way, oops sorry, console log, “hi”, make

    給帶有回調的URL 方法相同,啊抱歉,console.log(' Hi')

  • an AJAX request, the code for running that AJAX request does not live in JavaScript Runtime

    提出AJAX請求,我們用在執行該AJAX請求的程式碼 不在JavaScript Runtime裡面

  • but in the browser as a web API, so we spin it up with a callback in the URL, your code

    而是以Web API的樣子出現在瀏覽器裡 所以我們用URL裡的回調來啟動

  • can continue to run.

    你的程式碼能繼續執行了

  • Until that XHR request completes, or it may never complete, it's okay, the stack can continue

    在XHR請求完成之前,或者可能永遠不會完成之前 都沒有關係,堆疊可以繼續執行

  • to run, assuming it completes, gets pushed to the queue,picked up by the event loop and

    假設執行完了,它就會被推入佇列 被事件循環抓起來

  • it's run.

    然後它就會執行了

  • That's all that happens when an Async call happens.

    這就是非同步呼叫出現時 會出現的全部情況了

  • Let's do a crazy complicated example, I hope this going to work, if you haven't realized

    好,我們來做一個超級複雜的範例 我希望他能夠成功,如果你還沒有發現到

  • all this is in keynote there's like I don't know 500 animation steps in this whole deck.

    這些全都在演講主題之中,這投影片裡...我不知道 全部可能有500個動畫步驟

  • (code blows up, flames animation) (Applause) J Whew ... no ... so ... interesting, we're

    (代碼炸掉、動畫燒掉)(鼓掌) 噢…嗯…很有意思

  • given a link.

    我們得到了個連結

  • Hmm ... is this big enough, can people see?

    嗯...這樣夠大嗎?大家看得到嗎?

  • Okay, so basically I wrote this talk for Scotland JS, after the talk I broke half of the slides

    好,基本上我是今年早一點的時候,幫ScotlandJS大會 寫了這段演講,也講了一次,後來我弄壞了一半的投影片

  • and could not be bothered to redo all the slides because it was a total pain in the

    然後完全不想費心思重新做投影片 因為

  • ass in keynote to do it so I took much easier route (Laughing) of writing a tool that can

    實在太麻煩了,所以我採用了比較簡單的方式...(笑聲) 主要是在寫出一個能夠

  • visualize the JavaScript Runtime at Runtime, and it's called loop.

    在Runtime將JavaScript Runtime視覺化的工具 這個東西叫做迴圈

  • So, let's just run this example and, which was kind of the example that we had on the

    所以,我們就來執行這個範例 這有點像是我們在前一張投影片

  • previous slide, I haven't shimmed XHR yet, it's doable I just haven't done it.

    做的東西,我還沒有shim XHR 是可以這麼做,我只是還沒有做

  • As you can see the code, we're going to log something, this is a shim around addEventListener,

    如你所看到程式碼的樣子,我們要記錄一些內容 這個shim程序是針對addEventListener

  • setTimeout and we're going to do a console.log. ‑‑

    setTimeout,然後我們要做一個console.log

  • I'm going to run it and see what happens so ... add a DOM API, add a timeout, code is

    我接下來要執行它,看看會發生什麼事 所以呢,加一個DOM API,添加一個timeout

  • going to continue to run, pushes the callback into the queue which runs, and we're done.

    程式會繼續跑,將回調推到正在運行的佇列中 然後我們就完成了

  • If I click on here then it's going to ... trigger the web API, queue the callback for the click

    如果我點擊這裡,它就會...觸發Web API 為點擊動作將回調排入佇列

  • and run it.

    然後執行

  • if I cluck a hundred times we can see what happens.

    如果我點擊了一百次 我們就可以看到會發生什麼事,對吧?

  • I clicked, the click doesn't get processed immediately, itself gets pushed to the queue,

    我點擊了,但我這次點擊不會立即得到處理 它本身會被推入佇列

  • as the queue gets processed, eventually my click is going to get dealt with, right.

    隨著佇列得到處理 最終我的點擊也會得到處理,對吧?

  • So I have a few more examples I'm going to run through here.

    所以,我在這裡還有一些範例 要繼續帶大家看

  • Here we go, okay, so, I'm just going to run through a few examples just to kind of talk

    除了...我不知道怎麼看tab...好,要開始囉,好的,所以呢 我要通過幾個例子來說明

  • about a few things that you might have run in to and not thought about with Async APIs,

    一些可能在接觸非同步的API時 會遇到的一些事情,以及沒考慮過的事情

  • In this example we call setTimeout four times with the one second delay, and console.log

    在這個範例中,我們以一秒鐘的延遲 呼叫了setTimeout四次,然後執行

  • hi”.

    console.log('Hi') 所以,如果我們執行下去

  • By the time the callbacks get queued... that fourth callback we asked for a one second

    我們會看到執行了幾次限時,等到回調程序排進佇列時 我們要求要一秒鐘延遲的第四個回調程序

  • delay, and it's still waiting, the callback hasn't run, right .

    它還在等待,該次回調還沒執行,對吧?

  • this illustrates the ‑‑ like what time out is actually doing, it's not a guaranteed

    這有點說明了...就像限時實際上的功能 這並不是個

  • time to execution, it's a minimum time to execution, just like setTimeout zero doesn't

    執行上的保證,而是距離執行的最短時間 就像是setTimeout設定為零並不會

  • run the code immediately it runs the code nextish, sometime, right?

    立刻執行程式 而是接下來的某個時間才執行,對吧?

  • So ... in this example I want to talk about callbacks, so, depending on who, speak to

    所以呢,在這個範例中,我想談談回調 那麼,依據說話的對象

  • and how they phrase things, callbacks can be one of two things, callbacks can be any

    用字遣詞的方式 回調這個動作有兩種情況:回調可以是

  • function that another function calls or callbacks can be more explicitly an asynchronous callback

    任何一個函式所呼叫的任何一種函式 或者更明白地說,回調可以是非同步回調

  • as in one that will get pushed back on the callback queue in the future.

    在那種情況下,動作會在後來 被推回到回調佇列

  • This bit of code illustrates the difference, right.

    這段程式闡述了當中的區別

  • The forEach method on an array, it doesn't run, it takes a function, which you could

    在陣列上的forEach方法不會執行 它需要一個函式,你可以在之上

  • call a callback, but it's not running it asynchronously, it's running it within the current stack.

    呼叫一個回調,但是它不會非同步執行 而是在當前的堆疊中執行

  • We could define an asynchronous forEach so it can take an array, a callback and for each

    我們可以定義一個非同步的forEach 好讓它可以接受一個陣列、一個回調,並且在每個

  • item in the array it's going to do a setTimeout zero with that callback, I guess this should

    陣列中的項目上,它將使用這個回調 去執行設定為零的setTimeout,對吧,我想這應該

  • pass in the value, but any way, so, I'm going to run it and we can see what the difference

    要傳出值,不過...沒關係,所以呢 我接下來要執行它,然後看看有什麼不同

  • is, so for the first block of code that runs, it's going to sit and block the stack, right?

    所以對於執行的第一段程式 它將停下來,然後阻塞堆疊

  • Until it's complete, whereas in the Async version, okay, it's slowed down, but we're

    直到程式跑完為止,然而在非同步版本中 它的速度變慢了,但是我們

  • basically going to queue a bunch of callbacks and they're going to clear and then we can

    基本上要把一堆回調排進佇列 然後它們會清空,之後我們就可以

  • actually run through and do a console.log.

    實際整串去執行,並且用上console.log

  • In this example the console.log is fast, so the benefit of doing it asynchronously is

    在這個範例中,console.log的執行速度很快 非同步執行的好處

  • not obviously but let's say you're doing some slow processing on each element in the array.

    不太明顯,但假設你正在對陣列中的 每個元素進行某種緩慢的處理

  • I think I have that shown somewhere no, no, I don't.

    我覺得我有放在某個地方...沒有...我沒有

  • Okay.

  • So let's say ‑‑ Ooops.

    所以假設說...哎呀

  • So I have a delay function which is just slow, it's just a slow thing.

    所以我有一個延遲函式,它很慢 它就是個很慢的東西

  • So ... let's say processing Async and here processing Sync.

    所以...假設說處理非同步 然後這裡處理同步

  • Okay, now, I'm going to turn on a thing I've literally hacked together this morning, which

    好,現在我要打開一個 今天早上真的才湊在一起的東西

  • is to simulate the repaint or the render in the browser, something I haven't touched on

    這是用來在模擬瀏覽器中的重繪或顯示 我還沒碰過的部分是

  • is how all of this interacts with rendering ‑‑ I've kind of touched on it but not really

    所有的這些與顯示交互作用的方式 我算是有種碰過了,但還沒

  • explained it.

    講解到

  • So, basically the browser is kind of constrained by what you're doing javaScript, the browser

    因此,基本上瀏覽器算是 被你正在執行的JavaScript所約束

  • would like to repaint the screen every 16.6 milliseconds, 60 frame a second is ideal,

    瀏覽器想要每16.6毫秒重新繪製一次螢幕 每秒60幀是理想的選擇

  • that's the fastest it will do repaints if it can.

    那會是瀏覽器理想上會進行的 最快速的重新繪製的頻率

  • But it's constrained by what you're doing in JavaScript for various reasons, so it can't

    但是由於許多原因 它受到你在JavaScript中所做的操作的限制

  • actually do a render if there is code on the stack, right.

    所以當堆疊上有程式碼的時候 瀏覽器其實並不能顯示,對吧?

  • Like the render kind of call is almost like a callback in itself.

    顯示這樣的呼叫本身幾乎就像是回調

  • It has to wait till the stack is clear.

    它必須等到堆疊清空為止

  • The difference is that the render is given a higher priority than your callback, every

    差別在於,顯示的優先級別高於回調

  • 16 milliseconds it's going to queue a rend, wait till the stack is clear before it can

    它每16毫秒就會把顯示排進佇列 等到堆疊清空後,它才能

  • actually do that render.

    實際顯示畫面

  • So this is ‑‑ this render queue is just simulating a render, every second it's can

    所以這就是...這個顯示佇列只是在模擬顯示畫面 它每秒鐘都在問...

  • I do a render?

    我可以顯示畫面嗎?

  • Yes, can I do a render?

    可以,我可以顯示畫面嗎?

  • Yes.

    可以

  • Where, because our code isn't doing anything now.

    這裡的話,因為我們的程式碼現在什麼也沒做

  • If I run the code, you can see while we're doing this slow synchronous loop through the

    如果我運行程式,你就能看到 我們正在對這個陣列進行同步迴圈

  • array, our render is blocked, right, if our render is blocked you can't select text on

    我們的顯示被擋住了,對吧 如果我們的顯示被擋住了,你就無法在螢幕上

  • the screen, you can't click things and see the response, right, like the example I showed

    選擇文字,你無法點擊物件或是看到回應 就像我稍早的時候秀出來的

  • earlier.

    範例一樣

  • In this example, okay, it's blocked while we queue up the async time out, that relatively

    在這個例子中,好,它在我們排隊執行 非同步限時的時候被擋住了,那相對起來算快

  • quick but we're given ‑‑ we're kind of giving the render a chance between each element

    但是我們...我們算是在每個元素之間 給了顯示畫面一個機會

  • because we've queued it up asynchronously to jump in there and do the render, does that

    因為我們已經將它用非同步方式 排進佇列,好讓它能夠跳進來顯示

  • make sense?

    這邊可以懂嗎?

  • >> Yeah >> Yeah, cool.

  • So, that's just kind of ‑‑ this is just like a simulation of how the rendering works,

    所以,這只是...這像是一種模擬 模擬顯示畫面的運作方式

  • but it just really shows you when people say don't block the event loop, this is exactly

    但這裡確實向你展示了 當人們說不要阻塞事件循環時,他們在說的

  • what they're talking about.

    就是這個

  • They're saying don't put shitty slow code on the stack because when you do that the

    他們說的是,不要在堆疊上放慢到不行的程式 因為這樣做的話

  • browser can't do what it needs to do, create a nice fluid UI.

    瀏覽器就無法執行它需要做的工作 也就是建立一個品質好而流暢的UI

  • This is why when you're doing things like image processing or Animating too many things

    這就是為什麼當你執行像是圖像處理等等 或像是做太多動畫時

  • gets sluggish if you're not careful about how you queue up that code.

    要是你沒有注意程式碼是如何排進佇列的話 畫面就會變得遲鈍

  • So an example of that, we can see with the scroll handlers ‑‑ so scroll handle ‑‑

    所以這裡舉一個例子,我們可以用捲軸來看 所以,捲軸...

  • like scroll events in the DOM trigger a lot, right, they trigger like ‑‑ I presume

    就像DOM中的捲軸事件會觸發很多東西一樣 它們會觸發...我猜

  • they trigger on every frame like every 16 milliseconds, if I have code like this this

    如果我有這樣的程式碼 它們就可能會每16毫秒就在每一幀上觸發動作

  • right.

    對吧?

  • On document.scroll, animate something, or do some work.

    在document.scroll上,製作動畫或進行一些工作

  • If I have this code, like as I scroll it's going to queue up like a ton of callbacks

    如果我有這段程式碼,比如在我捲軸的時候 它就會像一大堆的回調一樣排進佇列

  • right.

    對吧?

  • And then it has to go through and process all of those and each of the processing of

    然後,它必須經歷並處理每個

  • those is slow, then, okay, you're not blocking the stack, you're flooding the queue with

    緩慢的程式碼...然後,好 你不再阻塞堆疊了,而是用排進佇列的事件

  • queued events.

    來淹沒整個佇列

  • So, this is like just helping visualize, I guess, what happens when you actually trigger

    所以,我想這是在幫助我們做視覺化 針對的是當實際觸發所有的回調時

  • all these callbacks, there's way you can debounce that to basically say okay, we're going to

    會發生什麼事,有一種方法是你可以 對其做防抖動,直到基本上你能說,好,我們要

  • queue up all those events, but let's do the slow work every few seconds or until the user

    把所有這些事件排進佇列,但我們要 每隔幾秒鐘慢慢做,或是直到使用者

  • stops scrolling for some amount of time I think that's basically it.

    不再使用捲軸一段時間 嗯...酷,我想內容基本上就是這樣

  • There's a whole other talk in how the hell this works.

    關於這到底是怎麼運作的 現場還有另一場分享

  • Because basically in running the code, like this code runs at Runtime, right, and it's

    因為,基本上在Runtime執行像這樣的程式碼的時候

  • slowed down by I run it through a Esprima a JavaScript parser, I insert a big while

    我用Esprima這個JavaScript的parser (語法分析器)的時候 程式會慢下來,在每行程式碼之前和之後,我都插入一個while迴圈

  • loop, that takes half a second, it just slow motions the code.

    執行它要花半秒鐘 所以它基本上會讓程式變得像在做慢動作

  • Ship it to web worker and do a whole bunch of stuff to visualize what's happening while

    把它運送給Web Worker,並進行大量工作 來對正在發生的事情做視覺化

  • doing it at run time that makes sense.

    這是在Runtime執行的時候,就是這樣子

  • A whole other talk in that.

    大會還會有一場完整的分享

  • I'm super excited about it and will talk to anyone about it after because I think it's

    我超級期待想要分享的 而且會在之後和任何有興趣的人交流,因為我覺得

  • kind of neat, so with that, thanks very much ( applause)

    這蠻讚的,那麼...以上 非常感謝大家聆聽(掌聲)

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

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

字幕與單字

單字即點即查 點擊單字可以查詢單字解釋