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

資訊專欄INFORMATION COLUMN

初窺JavaScript事件機(jī)制的實(shí)現(xiàn)(一)—— Node.js事件驅(qū)動(dòng)實(shí)現(xiàn)概覽

lavor / 3482人閱讀

摘要:如果當(dāng)前沒(méi)有事件也沒(méi)有定時(shí)器事件,則返回。相關(guān)資料關(guān)于的架構(gòu)及設(shè)計(jì)思路的事件討論了使用線程池異步運(yùn)行代碼。下一篇初窺事件機(jī)制的實(shí)現(xiàn)二中定時(shí)器的實(shí)現(xiàn)

在瀏覽器中,事件作為一個(gè)極為重要的機(jī)制,給予JavaScript響應(yīng)用戶操作與DOM變化的能力;在Node.js中,事件驅(qū)動(dòng)模型則是其高并發(fā)能力的基礎(chǔ)。

學(xué)習(xí)JavaScript也需要了解它的運(yùn)行平臺(tái),為了更好的理解JavaScript的事件模型,我打算從Node及瀏覽器引擎源碼入手,分析其底層實(shí)現(xiàn),并將我的分析整理為一系列博文;一方面作為筆記,另一方面也希望能與大家交流,分析和理解有疏漏偏頗之處,還望各位斧正。

簡(jiǎn)述事件驅(qū)動(dòng)模型

解釋JavaScript事件模型本身的好文章已經(jīng)很多了,可以說(shuō)這已經(jīng)是一個(gè)說(shuō)爛了的話題,這里我只簡(jiǎn)單寫(xiě)一下,并且提供一些好文章的鏈接。

程序如何響應(yīng)事件

我們的程序響應(yīng)外部的事件有如下兩種方式:

中斷
操作系統(tǒng)處理鍵盤(pán)等硬件輸入就是通過(guò)中斷來(lái)進(jìn)行的,這個(gè)方式的好處是即使沒(méi)有多線程,我們也可以放心地執(zhí)行我們的代碼,CPU收到中斷信號(hào)之后自動(dòng)地轉(zhuǎn)去執(zhí)行相應(yīng)的中斷處理程序,處理完成后會(huì)恢復(fù)原來(lái)的代碼的執(zhí)行環(huán)境繼續(xù)執(zhí)行。這種方式需要硬件的支持,一般來(lái)說(shuō)都會(huì)被操作系統(tǒng)封裝起來(lái)。

輪詢
循環(huán)檢測(cè)是否有事件發(fā)生,如果有就去執(zhí)行相應(yīng)的處理程序。這在底層和上層的開(kāi)發(fā)中都有應(yīng)用。
Windows窗口程序就需要在主線程中寫(xiě)下如下代碼,通常稱做消息循環(huán):

MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

消息循環(huán)不斷檢測(cè)是否有消息(用戶的UI操作、系統(tǒng)消息等)出現(xiàn),有的話就分發(fā)消息,調(diào)用相應(yīng)的回調(diào)函數(shù)進(jìn)行處理。
輪詢方式的一個(gè)缺點(diǎn)就是:如果在主線程的消息循環(huán)里進(jìn)行耗時(shí)操作,程序就無(wú)法及時(shí)響應(yīng)新的消息。這在JavaScript中表現(xiàn)明顯,以后還會(huì)提到這一點(diǎn),并探討其解決方案。

然而JavaScript中并沒(méi)有類似消息循環(huán)代碼,我們只是簡(jiǎn)單地注冊(cè)事件,然后等待被調(diào)用。這是因?yàn)闉g覽器、Node作為執(zhí)行平臺(tái),已經(jīng)將event loop實(shí)現(xiàn)了,JavaScript代碼不需要介入到這個(gè)過(guò)程中,只需要作為被調(diào)用者安靜地等待即可。

相關(guān)討論

知乎-關(guān)于瀏覽器處理事件的問(wèn)題?匿名用戶的回答:這個(gè)回答里圖很不錯(cuò),有助于理解event loop的工作原理;答案末尾有一些文章分享;

MDN - Concurrency model and Event Loop:MDN上對(duì)event loop的介紹。

Node中的event loop 通過(guò)Node源碼看event loop的實(shí)現(xiàn)

Node采用V8作為JavaScript的執(zhí)行引擎,同時(shí)使用libuv實(shí)現(xiàn)事件驅(qū)動(dòng)式異步I/O。其事件循環(huán)就是采用了libuv的默認(rèn)事件循環(huán)。

在src/node.cc中,

Environment* env = CreateEnvironment(
        node_isolate,
        uv_default_loop(),
        context,
        argc,
        argv,
        exec_argc,
        exec_argv);

這段代碼建立了一個(gè)node執(zhí)行環(huán)境,可以看到第三行的uv_default_loop(),這是libuv庫(kù)中的一個(gè)函數(shù),它會(huì)初始化uv庫(kù)本身以及其中的default_loop_struct,并返回一個(gè)指向它的指針default_loop_ptr
之后,Node會(huì)載入執(zhí)行環(huán)境并完成一些設(shè)置操作,然后啟動(dòng)event loop:

bool more;
do {
  more = uv_run(env->event_loop(), UV_RUN_ONCE);
  if (more == false) {
    EmitBeforeExit(env);
    // Emit `beforeExit` if the loop became alive either after emitting
    // event, or after running some callbacks.
    more = uv_loop_alive(env->event_loop());
    if (uv_run(env->event_loop(), UV_RUN_NOWAIT) != 0)
      more = true;
  }
} while (more == true);
code = EmitExit(env);
RunAtExit(env);
...

more用來(lái)標(biāo)識(shí)是否進(jìn)行下一輪循環(huán)。
env->event_loop()會(huì)返回之前保存在env中的default_loop_ptruv_run函數(shù)將以指定的UV_RUN_ONCE模式啟動(dòng)libuv的event loop。在這種模式下,uv_run會(huì)至少處理一個(gè)事件:這意味著,如果當(dāng)前事件隊(duì)列中沒(méi)有需要處理的I/O事件,uv_run會(huì)阻塞住,直到有I/O事件需要處理,或者下一個(gè)定時(shí)器時(shí)間到。如果當(dāng)前沒(méi)有I/O事件也沒(méi)有定時(shí)器事件,則uv_run返回false。

接下來(lái)Node會(huì)根據(jù)more的情況決定下一步操作:

如果moretrue,則繼續(xù)運(yùn)行下一輪loop

如果morefalse,說(shuō)明已經(jīng)沒(méi)有等待處理的事件了,EmitBeforeExit(env);觸發(fā)進(jìn)程的"beforeExit"事件,檢查并處理相應(yīng)的處理函數(shù),完成后直接跳出循環(huán)。

最后觸發(fā)"exit"事件,執(zhí)行相應(yīng)的回調(diào)函數(shù),Node運(yùn)行結(jié)束,后面會(huì)進(jìn)行一些資源釋放操作。

在libuv中,event loop會(huì)在每次循環(huán)的開(kāi)始更新自己的time從而實(shí)現(xiàn)計(jì)時(shí)功能,而I/O事件則分為兩類:

Network I/O是使用系統(tǒng)提供的非阻塞式I/O解決方案,例如在Linux上使用epoll,windows上使用IOCP。

文件操作和DNS操作沒(méi)有(很好的)系統(tǒng)解決方案,因此libuv自建了線程池,在其中進(jìn)行阻塞式I/O。

另外我們也可以將自定義的函數(shù)拋到線程池中運(yùn)行,在運(yùn)行結(jié)束后主線程會(huì)執(zhí)行相應(yīng)的回調(diào)函數(shù),不過(guò)Node并沒(méi)有將這一項(xiàng)功能加入到JavaScript中,也就是說(shuō)只用原生Node是無(wú)法在JavaScript中開(kāi)啟新的線程進(jìn)行并行執(zhí)行的。

相關(guān)資料

libuv Design Overview:關(guān)于libuv的架構(gòu)及設(shè)計(jì)思路;

node child_process "exit":Node的child_process "exit"事件;

Node with threads:討論了使用libuv線程池異步運(yùn)行JavaScript代碼。

下一篇: 初窺JavaScript事件機(jī)制的實(shí)現(xiàn)(二)—— Node.js中定時(shí)器的實(shí)現(xiàn)

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/85737.html

相關(guān)文章

  • 初窺JavaScript事件機(jī)制實(shí)現(xiàn)(二)—— Node.js中定時(shí)器實(shí)現(xiàn)

    摘要:下面通過(guò)幾個(gè)的定時(shí)器示例以及相關(guān)源碼來(lái)分析在中,功能到底是怎么實(shí)現(xiàn)的。我們知道,中的定時(shí)器并不同于計(jì)算機(jī)底層的定時(shí)中斷。補(bǔ)充資料在高級(jí)程序設(shè)計(jì)第三版第章高級(jí)技巧中對(duì)高級(jí)定時(shí)器以及有較詳細(xì)的討論。至此,這類定時(shí)器函數(shù)已經(jīng)可以為所用了。 上一篇博文提到,在Node中timer并不是通過(guò)新開(kāi)線程來(lái)實(shí)現(xiàn)的,而是直接在event loop中完成。下面通過(guò)幾個(gè)JavaScript的定時(shí)器示例以及N...

    novo 評(píng)論0 收藏0
  • [譯] Node.js 架構(gòu)概覽

    摘要:文件系統(tǒng)請(qǐng)求和相關(guān)請(qǐng)求都會(huì)放進(jìn)這個(gè)線程池處理其他的請(qǐng)求,如網(wǎng)絡(luò)平臺(tái)特性相關(guān)的請(qǐng)求會(huì)分發(fā)給相應(yīng)的系統(tǒng)處理單元參見(jiàn)設(shè)計(jì)概覽。 譯者按:在 Medium 上看到這篇文章,行文脈絡(luò)清晰,闡述簡(jiǎn)明利落,果斷點(diǎn)下翻譯按鈕。第一小節(jié)背景鋪陳略啰嗦,可以略過(guò)。剛開(kāi)始我給這部分留了個(gè) blah blah blah 直接翻后面的,翻完之后回頭看,考慮完整性才把第一節(jié)給補(bǔ)上。接下來(lái)的內(nèi)容干貨滿滿,相信對(duì) N...

    antyiwei 評(píng)論0 收藏0
  • 【譯】node js event loop part 1.1

    原文 先說(shuō)1.1總攬: Reactor模式 Reactor模式中的協(xié)調(diào)機(jī)制Event Loop Reactor模式中的事件分離器Event Demultiplexer 一些Event Demultiplexer處理不了的復(fù)雜I/O接口比如File I/O、DNS等 復(fù)雜I/O的解決方案 未完待續(xù) 前言 nodejs和其他編程平臺(tái)的區(qū)別在于如何去處理I/O接口,我們聽(tīng)一個(gè)人介紹nodejs,總是...

    macg0406 評(píng)論0 收藏0
  • JavaScript Event loop 事件循環(huán)

    摘要:階段有兩個(gè)主要功能也會(huì)執(zhí)行時(shí)間定時(shí)器到達(dá)期望時(shí)間的回調(diào)函數(shù)執(zhí)行事件循環(huán)列表里的函數(shù)當(dāng)進(jìn)入階段并且沒(méi)有其余的定時(shí)器,那么如果事件循環(huán)列表不為空,則迭代同步的執(zhí)行隊(duì)列中的函數(shù)。如果沒(méi)有,則等待回調(diào)函數(shù)進(jìn)入隊(duì)列并立即執(zhí)行。 Event Loop 本文以 Node.js 為例,講解 Event Loop 在 Node.js 的實(shí)現(xiàn),原文,JavaScript 中的實(shí)現(xiàn)大同小異。 什么是 Eve...

    luckyyulin 評(píng)論0 收藏0
  • node核心特性理解

    摘要:概述本文主要介紹了我對(duì)的一些核心特性的理解,包括架構(gòu)特點(diǎn)機(jī)制核心模塊與簡(jiǎn)單應(yīng)用。在此期間,主線程繼續(xù)執(zhí)行其他任務(wù)。延續(xù)了瀏覽器端單線程,只用一個(gè)主線程執(zhí)行,不斷循環(huán)遍歷事件隊(duì)列,執(zhí)行事件。 原文地址在我的博客,轉(zhuǎn)載請(qǐng)注明來(lái)源,謝謝! node是在前端領(lǐng)域經(jīng)常看到的詞。node對(duì)于前端的重要性已經(jīng)不言而喻,掌握node也是作為合格的前端工程師一項(xiàng)基本功了。知道node、知道后端的一些東西...

    huangjinnan 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

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