国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

微任務(wù)、宏任務(wù)與Event-Loop

Nekron / 2339人閱讀

摘要:所以本來快輪到你來辦理業(yè)務(wù),會(huì)因?yàn)槔洗鬆斉R時(shí)添加的理財(cái)業(yè)務(wù)而往后推。在執(zhí)行完同步代碼與微任務(wù)以后,這時(shí)繼續(xù)向后查找有木有宏任務(wù)。所以輸出了第二次,等到這兩次都執(zhí)行完畢后才會(huì)去檢查有沒有微任務(wù)有沒有宏任務(wù)。

首先,JavaScript是一個(gè)單線程的腳本語言。
所以就是說在一行代碼執(zhí)行的過程中,必然不會(huì)存在同時(shí)執(zhí)行的另一行代碼,就像使用alert()以后進(jìn)行瘋狂console.log,如果沒有關(guān)閉彈框,控制臺是不會(huì)顯示出一條log信息的。
亦或者有些代碼執(zhí)行了大量計(jì)算,比方說在前端暴力破解密碼之類的鬼操作,這就會(huì)導(dǎo)致后續(xù)代碼一直在等待,頁面處于假死狀態(tài),因?yàn)榍斑叺拇a并沒有執(zhí)行完。

所以如果全部代碼都是同步執(zhí)行的,這會(huì)引發(fā)很嚴(yán)重的問題,比方說我們要從遠(yuǎn)端獲取一些數(shù)據(jù),難道要一直循環(huán)代碼去判斷是否拿到了返回結(jié)果么?_就像去飯店點(diǎn)餐,肯定不能說點(diǎn)完了以后就去后廚催著人炒菜的,會(huì)被揍的。_
于是就有了異步事件的概念,注冊一個(gè)回調(diào)函數(shù),比如說發(fā)一個(gè)網(wǎng)絡(luò)請求,我們告訴主程序等到接收到數(shù)據(jù)后通知我,然后我們就可以去做其他的事情了。
然后在異步完成后,會(huì)通知到我們,但是此時(shí)可能程序正在做其他的事情,所以即使異步完成了也需要在一旁等待,等到程序空閑下來才有時(shí)間去看哪些異步已經(jīng)完成了,可以去執(zhí)行。
比如說打了個(gè)車,如果司機(jī)先到了,但是你手頭還有點(diǎn)兒事情要處理,這時(shí)司機(jī)是不可能自己先開著車走的,一定要等到你處理完事情上了車才能走。

微任務(wù)與宏任務(wù)的區(qū)別

這個(gè)就像去銀行辦業(yè)務(wù)一樣,先要取號進(jìn)行排號。
一般上邊都會(huì)印著類似:“您的號碼為XX,前邊還有XX人。”之類的字樣。

因?yàn)楣駟T同時(shí)職能處理一個(gè)來辦理業(yè)務(wù)的客戶,這時(shí)每一個(gè)來辦理業(yè)務(wù)的人就可以認(rèn)為是銀行柜員的一個(gè)宏任務(wù)來存在的,當(dāng)柜員處理完當(dāng)前客戶的問題以后,選擇接待下一位,廣播報(bào)號,也就是下一個(gè)宏任務(wù)的開始。
所以多個(gè)宏任務(wù)合在一起就可以認(rèn)為說有一個(gè)任務(wù)隊(duì)列在這,里邊是當(dāng)前銀行中所有排號的客戶。
任務(wù)隊(duì)列中的都是已經(jīng)完成的異步操作,而不是說注冊一個(gè)異步任務(wù)就會(huì)被放在這個(gè)任務(wù)隊(duì)列中,就像在銀行中排號,如果叫到你的時(shí)候你不在,那么你當(dāng)前的號牌就作廢了,柜員會(huì)選擇直接跳過進(jìn)行下一個(gè)客戶的業(yè)務(wù)處理,等你回來以后還需要重新取號

而且一個(gè)宏任務(wù)在執(zhí)行的過程中,是可以添加一些微任務(wù)的,就像在柜臺辦理業(yè)務(wù),你前邊的一位老大爺可能在存款,在存款這個(gè)業(yè)務(wù)辦理完以后,柜員會(huì)問老大爺還有沒有其他需要辦理的業(yè)務(wù),這時(shí)老大爺想了一下:“最近P2P爆雷有點(diǎn)兒多,是不是要選擇穩(wěn)一些的理財(cái)呢”,然后告訴柜員說,要辦一些理財(cái)?shù)臉I(yè)務(wù),這時(shí)候柜員肯定不能告訴老大爺說:“您再上后邊取個(gè)號去,重新排隊(duì)”。
所以本來快輪到你來辦理業(yè)務(wù),會(huì)因?yàn)槔洗鬆斉R時(shí)添加的“理財(cái)業(yè)務(wù)”而往后推。
也許老大爺在辦完理財(cái)以后還想 再辦一個(gè)信用卡?或者 再買點(diǎn)兒紀(jì)念幣
無論是什么需求,只要是柜員能夠幫她辦理的,都會(huì)在處理你的業(yè)務(wù)之前來做這些事情,這些都可以認(rèn)為是微任務(wù)。

這就說明:你大爺永遠(yuǎn)是你大爺
在當(dāng)前的微任務(wù)沒有執(zhí)行完成時(shí),是不會(huì)執(zhí)行下一個(gè)宏任務(wù)的。

所以就有了那個(gè)經(jīng)常在面試題、各種博客中的代碼片段:

setTimeout(_ => console.log(4))

new Promise(resolve => {
  resolve()
  console.log(1)
}).then(_ => {
  console.log(3)
})

console.log(2)

setTimeout就是作為宏任務(wù)來存在的,而Promise.then則是具有代表性的微任務(wù),上述代碼的執(zhí)行順序就是按照序號來輸出的。

所有會(huì)進(jìn)入的異步都是指的事件回調(diào)中的那部分代碼
也就是說new Promise在實(shí)例化的過程中所執(zhí)行的代碼都是同步進(jìn)行的,而then中注冊的回調(diào)才是異步執(zhí)行的。
在同步代碼執(zhí)行完成后才回去檢查是否有異步任務(wù)完成,并執(zhí)行對應(yīng)的回調(diào),而微任務(wù)又會(huì)在宏任務(wù)之前執(zhí)行。
所以就得到了上述的輸出結(jié)論1、2、3、4

+部分表示同步執(zhí)行的代碼

+setTimeout(_ => {
-  console.log(4)
+})

+new Promise(resolve => {
+  resolve()
+  console.log(1)
+}).then(_ => {
-  console.log(3)
+})

+console.log(2)

本來setTimeout已經(jīng)先設(shè)置了定時(shí)器(相當(dāng)于取號),然后在當(dāng)前進(jìn)程中又添加了一些Promise的處理(臨時(shí)添加業(yè)務(wù))。

所以進(jìn)階的,即便我們繼續(xù)在Promise中實(shí)例化Promise,其輸出依然會(huì)早于setTimeout的宏任務(wù):

setTimeout(_ => console.log(4))

new Promise(resolve => {
  resolve()
  console.log(1)
}).then(_ => {
  console.log(3)
  Promise.resolve().then(_ => {
    console.log("before timeout")
  }).then(_ => {
    Promise.resolve().then(_ => {
      console.log("also before timeout")
    })
  })
})

console.log(2)

當(dāng)然了,實(shí)際情況下很少會(huì)有簡單的這么調(diào)用Promise的,一般都會(huì)在里邊有其他的異步操作,比如fetchfs.readFile之類的操作。
而這些其實(shí)就相當(dāng)于注冊了一個(gè)宏任務(wù),而非是微任務(wù)。

P.S. 在Promise/A+的規(guī)范中,Promise的實(shí)現(xiàn)可以是微任務(wù),也可以是宏任務(wù),但是普遍的共識表示(至少Chrome是這么做的),Promise應(yīng)該是屬于微任務(wù)陣營的

所以,明白哪些操作是宏任務(wù)、哪些是微任務(wù)就變得很關(guān)鍵,這是目前業(yè)界比較流行的說法:

宏任務(wù)
# 瀏覽器 Node
I/O ? ?
setTimeout ? ?
setInterval ? ?
setImmediate ? ?
requestAnimationFrame ? ?

有些地方會(huì)列出來UI Rendering,說這個(gè)也是宏任務(wù),可是在讀了HTML規(guī)范文檔以后,發(fā)現(xiàn)這很顯然是和微任務(wù)平行的一個(gè)操作步驟
requestAnimationFrame姑且也算是宏任務(wù)吧,requestAnimationFrame在MDN的定義為,下次頁面重繪前所執(zhí)行的操作,而重繪也是作為宏任務(wù)的一個(gè)步驟來存在的,且該步驟晚于微任務(wù)的執(zhí)行

微任務(wù)
# 瀏覽器 Node
process.nextTick ? ?
MutationObserver ? ?
Promise.then catch finally ? ?
Event-Loop是個(gè)啥

上邊一直在討論 宏任務(wù)、微任務(wù),各種任務(wù)的執(zhí)行。
但是回到現(xiàn)實(shí),JavaScript是一個(gè)單進(jìn)程的語言,同一時(shí)間不能處理多個(gè)任務(wù),所以何時(shí)執(zhí)行宏任務(wù),何時(shí)執(zhí)行微任務(wù)?我們需要有這樣的一個(gè)判斷邏輯存在。

每辦理完一個(gè)業(yè)務(wù),柜員就會(huì)問當(dāng)前的客戶,是否還有其他需要辦理的業(yè)務(wù)。_(檢查還有沒有微任務(wù)需要處理)_
而客戶明確告知說沒有事情以后,柜員就去查看后邊還有沒有等著辦理業(yè)務(wù)的人。_(結(jié)束本次宏任務(wù)、檢查還有沒有宏任務(wù)需要處理)_
這個(gè)檢查的過程是持續(xù)進(jìn)行的,每完成一個(gè)任務(wù)都會(huì)進(jìn)行一次,而這樣的操作就被稱為Event Loop。_(這是個(gè)非常簡易的描述了,實(shí)際上會(huì)復(fù)雜很多)_

而且就如同上邊所說的,一個(gè)柜員同一時(shí)間只能處理一件事情,即便這些事情是一個(gè)客戶所提出的,所以可以認(rèn)為微任務(wù)也存在一個(gè)隊(duì)列,大致是這樣的一個(gè)邏輯:

const macroTaskList = [
  ["task1"],
  ["task2", "task3"],
  ["task4"],
]

for (let macroIndex = 0; macroIndex < macroTaskList.length; macroIndex++) {
  const microTaskList = macroTaskList[macroIndex]
  
  for (let microIndex = 0; microIndex < microTaskList.length; microIndex++) {
    const microTask = microTaskList[microIndex]

    // 添加一個(gè)微任務(wù)
    if (microIndex === 1) microTaskList.push("special micro task")
    
    // 執(zhí)行任務(wù)
    console.log(microTask)
  }

  // 添加一個(gè)宏任務(wù)
  if (macroIndex === 2) macroTaskList.push(["special macro task"])
}

// > task1
// > task2
// > task3
// > special micro task
// > task4
// > special macro task

之所以使用兩個(gè)for循環(huán)來表示,是因?yàn)樵谘h(huán)內(nèi)部可以很方便的進(jìn)行push之類的操作(添加一些任務(wù)),從而使迭代的次數(shù)動(dòng)態(tài)的增加。

以及還要明確的是,Event Loop只是負(fù)責(zé)告訴你該執(zhí)行那些任務(wù),或者說哪些回調(diào)被觸發(fā)了,真正的邏輯還是在進(jìn)程中執(zhí)行的。

在瀏覽器中的表現(xiàn)

在上邊簡單的說明了兩種任務(wù)的差別,以及Event Loop的作用,那么在真實(shí)的瀏覽器中是什么表現(xiàn)呢?
首先要明確的一點(diǎn)是,宏任務(wù)必然是在微任務(wù)之后才執(zhí)行的(因?yàn)槲⑷蝿?wù)實(shí)際上是宏任務(wù)的其中一個(gè)步驟)

I/O這一項(xiàng)感覺有點(diǎn)兒籠統(tǒng),有太多的東西都可以稱之為I/O,點(diǎn)擊一次button,上傳一個(gè)文件,與程序產(chǎn)生交互的這些都可以稱之為I/O

假設(shè)有這樣的一些DOM結(jié)構(gòu):


const $inner = document.querySelector("#inner")
const $outer = document.querySelector("#outer")

function handler () {
  console.log("click") // 直接輸出

  Promise.resolve().then(_ => console.log("promise")) // 注冊微任務(wù)

  setTimeout(_ => console.log("timeout")) // 注冊宏任務(wù)

  requestAnimationFrame(_ => console.log("animationFrame")) // 注冊宏任務(wù)

  $outer.setAttribute("data-random", Math.random()) // DOM屬性修改,觸發(fā)微任務(wù)
}

new MutationObserver(_ => {
  console.log("observer")
}).observe($outer, {
  attributes: true
})

$inner.addEventListener("click", handler)
$outer.addEventListener("click", handler)

如果點(diǎn)擊#inner,其執(zhí)行順序一定是:click -> promise -> observer -> click -> promise -> observer -> animationFrame -> animationFrame -> timeout -> timeout

因?yàn)橐淮?b>I/O創(chuàng)建了一個(gè)宏任務(wù),也就是說在這次任務(wù)中會(huì)去觸發(fā)handler
按照代碼中的注釋,在同步的代碼已經(jīng)執(zhí)行完以后,這時(shí)就會(huì)去查看是否有微任務(wù)可以執(zhí)行,然后發(fā)現(xiàn)了PromiseMutationObserver兩個(gè)微任務(wù),遂執(zhí)行之。
因?yàn)?b>click事件會(huì)冒泡,所以對應(yīng)的這次I/O會(huì)觸發(fā)兩次handler函數(shù)(_一次在inner、一次在outer_),所以會(huì)優(yōu)先執(zhí)行冒泡的事件(_早于其他的宏任務(wù)_),也就是說會(huì)重復(fù)上述的邏輯。
在執(zhí)行完同步代碼與微任務(wù)以后,這時(shí)繼續(xù)向后查找有木有宏任務(wù)。
需要注意的一點(diǎn)是,因?yàn)槲覀冇|發(fā)了setAttribute,實(shí)際上修改了DOM的屬性,這會(huì)導(dǎo)致頁面的重繪,而這個(gè)set的操作是同步執(zhí)行的,也就是說requestAnimationFrame的回調(diào)會(huì)早于setTimeout所執(zhí)行。

一些小驚喜

使用上述的示例代碼,如果將手動(dòng)點(diǎn)擊DOM元素的觸發(fā)方式變?yōu)?b>$inner.click(),那么會(huì)得到不一樣的結(jié)果。
Chrome下的輸出順序大致是這樣的:
click -> click -> promise -> observer -> promise -> animationFrame -> animationFrame -> timeout -> timeout

與我們手動(dòng)觸發(fā)click的執(zhí)行順序不一樣的原因是這樣的,因?yàn)椴⒉皇怯脩敉ㄟ^點(diǎn)擊元素實(shí)現(xiàn)的觸發(fā)事件,而是類似dispatchEvent這樣的方式,我個(gè)人覺得并不能算是一個(gè)有效的I/O,在執(zhí)行了一次handler回調(diào)注冊了微任務(wù)、注冊了宏任務(wù)以后,實(shí)際上外邊的$inner.click()并沒有執(zhí)行完。
所以在微任務(wù)執(zhí)行之前,還要繼續(xù)冒泡執(zhí)行下一次事件,也就是說觸發(fā)了第二次的handler
所以輸出了第二次click,等到這兩次handler都執(zhí)行完畢后才會(huì)去檢查有沒有微任務(wù)、有沒有宏任務(wù)。

兩點(diǎn)需要注意的:

.click()的這種觸發(fā)事件的方式個(gè)人認(rèn)為是類似dispatchEvent,可以理解為同步執(zhí)行的代碼

document.body.addEventListener("click", _ => console.log("click"))

document.body.click()
document.body.dispatchEvent(new Event("click"))
console.log("done")

// > click
// > click
// > done

MutationObserver的監(jiān)聽不會(huì)說同時(shí)觸發(fā)多次,多次修改只會(huì)有一次回調(diào)被觸發(fā)。

new MutationObserver(_ => {
  console.log("observer")
  // 如果在這輸出DOM的data-random屬性,必然是最后一次的值,不解釋了
}).observe(document.body, {
  attributes: true
})

document.body.setAttribute("data-random", Math.random())
document.body.setAttribute("data-random", Math.random())
document.body.setAttribute("data-random", Math.random())

// 只會(huì)輸出一次 ovserver

這就像去飯店點(diǎn)餐,服務(wù)員喊了三次,XX號的牛肉面,不代表她會(huì)給你三碗牛肉面。
上述觀點(diǎn)參閱自Tasks, microtasks, queues and schedules,文中有動(dòng)畫版的講解

在Node中的表現(xiàn)

Node也是單線程,但是在處理Event Loop上與瀏覽器稍微有些不同,這里是Node官方文檔的地址。

就單從API層面上來理解,Node新增了兩個(gè)方法可以用來使用:微任務(wù)的process.nextTick以及宏任務(wù)的setImmediate

setImmediate與setTimeout的區(qū)別

在官方文檔中的定義,setImmediate為一次Event Loop執(zhí)行完畢后調(diào)用。
setTimeout則是通過計(jì)算一個(gè)延遲時(shí)間后進(jìn)行執(zhí)行。

但是同時(shí)還提到了如果在主進(jìn)程中直接執(zhí)行這兩個(gè)操作,很難保證哪個(gè)會(huì)先觸發(fā)。
因?yàn)槿绻鬟M(jìn)程中先注冊了兩個(gè)任務(wù),然后執(zhí)行的代碼耗時(shí)超過XXs,而這時(shí)定時(shí)器已經(jīng)處于可執(zhí)行回調(diào)的狀態(tài)了。
所以會(huì)先執(zhí)行定時(shí)器,而執(zhí)行完定時(shí)器以后才是結(jié)束了一次Event Loop,這時(shí)才會(huì)執(zhí)行setImmediate

setTimeout(_ => console.log("setTimeout"))
setImmediate(_ => console.log("setImmediate"))

有興趣的可以自己試驗(yàn)一下,執(zhí)行多次真的會(huì)得到不同的結(jié)果。

但是如果后續(xù)添加一些代碼以后,就可以保證setTimeout一定會(huì)在setImmediate之前觸發(fā)了:

setTimeout(_ => console.log("setTimeout"))
setImmediate(_ => console.log("setImmediate"))

let countdown = 1e9

while(countdown--) { } // 我們確保這個(gè)循環(huán)的執(zhí)行速度會(huì)超過定時(shí)器的倒計(jì)時(shí),導(dǎo)致這輪循環(huán)沒有結(jié)束時(shí),setTimeout已經(jīng)可以執(zhí)行回調(diào)了,所以會(huì)先執(zhí)行`setTimeout`再結(jié)束這一輪循環(huán),也就是說開始執(zhí)行`setImmediate`

如果在另一個(gè)宏任務(wù)中,必然是setImmediate先執(zhí)行:

require("fs").readFile(__dirname, _ => {
  setTimeout(_ => console.log("timeout"))
  setImmediate(_ => console.log("immediate"))
})

// 如果使用一個(gè)設(shè)置了延遲的setTimeout也可以實(shí)現(xiàn)相同的效果
process.nextTick

就像上邊說的,這個(gè)可以認(rèn)為是一個(gè)類似于PromiseMutationObserver的微任務(wù)實(shí)現(xiàn),在代碼執(zhí)行的過程中可以隨時(shí)插入nextTick,并且會(huì)保證在下一個(gè)宏任務(wù)開始之前所執(zhí)行。

在使用方面的一個(gè)最常見的例子就是一些事件綁定類的操作:

class Lib extends require("events").EventEmitter {
  constructor () {
    super()

    this.emit("init")
  }
}

const lib = new Lib()

lib.on("init", _ => {
  // 這里將永遠(yuǎn)不會(huì)執(zhí)行
  console.log("init!")
})

因?yàn)樯鲜龅拇a在實(shí)例化Lib對象時(shí)是同步執(zhí)行的,在實(shí)例化完成以后就立馬發(fā)送了init事件。
而這時(shí)在外層的主程序還沒有開始執(zhí)行到lib.on("init")監(jiān)聽事件的這一步。
所以會(huì)導(dǎo)致發(fā)送事件時(shí)沒有回調(diào),回調(diào)注冊后事件不會(huì)再次發(fā)送。

我們可以很輕松的使用process.nextTick來解決這個(gè)問題:

class Lib extends require("events").EventEmitter {
  constructor () {
    super()

    process.nextTick(_ => {
      this.emit("init")
    })

    // 同理使用其他的微任務(wù)
    // 比如Promise.resolve().then(_ => this.emit("init"))
    // 也可以實(shí)現(xiàn)相同的效果
  }
}

這樣會(huì)在主進(jìn)程的代碼執(zhí)行完畢后,程序空閑時(shí)觸發(fā)Event Loop流程查找有沒有微任務(wù),然后再發(fā)送init事件。

關(guān)于有些文章中提到的,循環(huán)調(diào)用process.nextTick會(huì)導(dǎo)致報(bào)警,后續(xù)的代碼永遠(yuǎn)不會(huì)被執(zhí)行,這是對的,參見上邊使用的雙重循環(huán)實(shí)現(xiàn)的loop即可,相當(dāng)于在每次for循環(huán)執(zhí)行中都對數(shù)組進(jìn)行了push操作,這樣循環(huán)永遠(yuǎn)也不會(huì)結(jié)束

多提一嘴async/await函數(shù)

因?yàn)椋?b>async/await本質(zhì)上還是基于Promise的一些封裝,而Promise是屬于微任務(wù)的一種。所以在使用await關(guān)鍵字與Promise.then效果類似:

setTimeout(_ => console.log(4))

async function main() {
  console.log(1)
  await Promise.resolve()
  console.log(3)
}

main()

console.log(2)

async函數(shù)在await之前的代碼都是同步執(zhí)行的,可以理解為await之前的代碼屬于new Promise時(shí)傳入的代碼,await之后的所有代碼都是在Promise.then中的回調(diào)

小節(jié)

JavaScript的代碼運(yùn)行機(jī)制在網(wǎng)上有好多文章都寫,本人道行太淺,只能簡單的說一下自己對其的理解。
并沒有去生摳文檔,一步一步的列出來,像什么查看當(dāng)前棧、執(zhí)行選中的任務(wù)隊(duì)列,各種balabala。
感覺對實(shí)際寫代碼沒有太大幫助,不如簡單的入個(gè)門,掃個(gè)盲,大致了解一下這是個(gè)什么東西就好了。

推薦幾篇參閱的文章:

tasks-microtasks-queues-and-schedules

understanding-js-the-event-loop

理解Node.js里的process.nextTick()

瀏覽器中的EventLoop說明文檔

Node中的EventLoop說明文檔

requestAnimationFrame | MDN

MutationObserver | MDN

One more things

Blued前端/Node團(tuán)隊(duì)招人。。初中高都有HC
坐標(biāo)帝都朝陽雙井,有興趣的請聯(lián)系我:
wechat: github_jiasm
mail: jiashunming@blued.com

歡迎砸簡歷

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/108240.html

相關(guān)文章

  • 徹底搞懂瀏覽器Event-loop

    摘要:檢查宏任務(wù)隊(duì)列,發(fā)現(xiàn)有的回調(diào)函數(shù)立即執(zhí)行回調(diào)函數(shù)輸出。接著遇到它的作用是在后將回調(diào)函數(shù)放到宏任務(wù)隊(duì)列中這個(gè)任務(wù)在再下一次的事件循環(huán)中執(zhí)行。 為什么會(huì)寫這篇博文呢? 前段時(shí)間,和頭條的小伙伴聊天問頭條面試前端會(huì)問哪些問題,他稱如果是他面試的話,event-loop肯定是要問的。那天聊了蠻多,event-loop算是給我留下了很深的印象,原因很簡單,因?yàn)橹拔覐奈瓷钊肓私膺^,如果是面試的時(shí)...

    source 評論0 收藏0
  • JavaScript的event-loop

    摘要:從誕生之日起就是一門單線程的非阻塞的腳本語言。這意味著這些線程實(shí)際上應(yīng)屬于主線程的子線程。所以嚴(yán)格來講這些線程并沒有完整的功能,也因此這項(xiàng)技術(shù)并非改變了語言的單線程本質(zhì)。函數(shù)執(zhí)行棧和事件隊(duì)列 瀏覽器渲染 從耗時(shí)的角度,瀏覽器請求、加載、渲染一個(gè)頁面,時(shí)間花在下面五件事情上:1.DNS 查詢2.TCP 連接3.HTTP 請求即響應(yīng)4.服務(wù)器響應(yīng)5.客戶端渲染 這里重點(diǎn)討論第五個(gè)部分,即瀏...

    aboutU 評論0 收藏0
  • 結(jié)合microtask和macrotask理解event-loop

    摘要:講的很清晰,看完之后更深一步的理解了事件循環(huán)機(jī)制。簡短的概述下總結(jié)是一個(gè)宏任務(wù)源,寫在里面的回調(diào)函數(shù)會(huì)加到宏任務(wù)隊(duì)列中。至此,一輪的事件循環(huán)已經(jīng)執(zhí)行完畢,開啟新的一輪事件循環(huán)。這就是整段代碼執(zhí)行情況的理解。 這篇文章真的是好文。講的很清晰,看完之后更深一步的理解了事件循環(huán)機(jī)制。 http://www.jianshu.com/p/12b9... 簡短的概述下總結(jié) setTimeout是一...

    sarva 評論0 收藏0
  • 淺析 event-loop 事件輪詢

    摘要:如果執(zhí)行的準(zhǔn)備時(shí)間大于了,因?yàn)閳?zhí)行同步代碼后,定時(shí)器的回調(diào)已經(jīng)被放入隊(duì)列,所以會(huì)先執(zhí)行隊(duì)列。 showImg(https://segmentfault.com/img/remote/1460000018998584); 閱讀原文 瀏覽器中的事件輪詢 JavaScript 是一門單線程語言,之所以說是單線程,是因?yàn)樵跒g覽器中,如果是多線程,并且兩個(gè)線程同時(shí)操作了同一個(gè) Dom 元素,...

    2501207950 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<