最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Node.js事件驅(qū)動

 更新時間:2015年06月18日 11:40:56   投稿:hebedich  
Node.Js是基于javascript語言,建構(gòu)在google V8 engine以及Linux上的一個非阻塞事件驅(qū)動IO框架。這里主要不是介紹nodejs具體應用代碼,而是想介紹一下事件驅(qū)動編程。

Node.js事件驅(qū)動實現(xiàn)概覽

雖然在ECMAScript的標準里并沒有(也沒有必要)明確規(guī)定“事件”,但是在瀏覽器中,事件作為一個極為重要的機制,給予JavaScript響應用戶操作與DOM變化的能力;在Node.js中,異步事件驅(qū)動模型則是其高并發(fā)能力的基礎。

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

簡述事件驅(qū)動模型

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

程序如何響應事件

我們的程序響應外部的事件有如下兩種方式:

中斷

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

輪詢

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

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

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

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

Node中的event loop

通過Node源碼看event loop的實現(xiàn)

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

在src/node.cc中,

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

這段代碼建立了一個node執(zhí)行環(huán)境,可以看到第三行的uv_default_loop(),這是libuv庫中的一個函數(shù),它會初始化uv庫本身以及其中的default_loop_struct,并返回一個指向它的指針default_loop_ptr。
之后,Node會載入執(zhí)行環(huán)境并完成一些設置操作,然后啟動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用來標識是否進行下一輪循環(huán)。

env->event_loop()會返回之前保存在env中的default_loop_ptr,uv_run函數(shù)將以指定的UV_RUN_ONCE模式啟動libuv的event loop。在這種模式下,uv_run會至少處理一個事件:這意味著,如果當前事件隊列中沒有需要處理的I/O事件,uv_run會阻塞住,直到有I/O事件需要處理,或者下一個定時器時間到。如果當前沒有I/O事件也沒有定時器事件,則uv_run返回false。

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

如果more為true,則繼續(xù)運行下一輪loop。

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

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

在libuv中,定時器事件是直接在event loop中處理的,而I/O事件則分為兩類:

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

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

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

以上所述就是本文的全部內(nèi)容了,希望大家能夠喜歡。

相關(guān)文章

  • node.js入門學習之url模塊

    node.js入門學習之url模塊

    最近在學習nodejs,知道了如何用nodejs創(chuàng)建一個簡單的小項目。例如如何創(chuàng)建一個服務器啦,例如http.createServer,還有根據(jù)不同的請求路徑來設置路由選擇啦,模塊引入,創(chuàng)建模塊啦,下面這篇文章主要介紹了node.js中url模塊的相關(guān)資料,需要的朋友可以參考下。
    2017-02-02
  • Node.js API詳解之 os模塊用法實例分析

    Node.js API詳解之 os模塊用法實例分析

    這篇文章主要介紹了Node.js API詳解之 os模塊用法,結(jié)合實例形式分析了Node.js API中os模塊基本功能、原理、用法及操作注意事項,需要的朋友可以參考下
    2020-05-05
  • Express作者TJ告別Node.js奔向Go

    Express作者TJ告別Node.js奔向Go

    TJ自我介紹: TJ Holowaychuk ,程序員兼藝術(shù)家,Koa、Co、Express、jade、mocha、node-canvas、commander.js等知名開源項目的創(chuàng)建和貢獻者。
    2014-07-07
  • 利用Node.js檢測端口是否被占用的方法

    利用Node.js檢測端口是否被占用的方法

    這篇文章主要給大家介紹了關(guān)于利用Node.js檢測端口是否被占用的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。
    2017-12-12
  • electron demo項目npm install安裝失敗的解決方法

    electron demo項目npm install安裝失敗的解決方法

    下面小編就為大家分享一篇electron demo項目npm install安裝失敗的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-02-02
  • 用nodejs實現(xiàn)json和jsonp服務的方法

    用nodejs實現(xiàn)json和jsonp服務的方法

    本篇文章主要介紹了用nodejs實現(xiàn)json和jsonp服務的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • NodeJS如何實現(xiàn)同步的方法示例

    NodeJS如何實現(xiàn)同步的方法示例

    nodeJS最大的特點就是其異步操作,下面這篇文章主要給大家介紹了關(guān)于NodeJS如何實現(xiàn)同步的方法的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學習學習吧
    2018-08-08
  • Node.js系列之發(fā)起get/post請求(2)

    Node.js系列之發(fā)起get/post請求(2)

    這篇文章主要為大家詳細介紹了Node.js系列之發(fā)起get/post請求,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • 詳解nvm管理多版本node踩坑

    詳解nvm管理多版本node踩坑

    這篇文章主要介紹了詳解nvm管理多版本node踩坑,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-07-07
  • npm ci命令的基本使用方法

    npm ci命令的基本使用方法

    這篇文章主要給大家介紹了關(guān)于npm ci命令的基本使用方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-09-09

最新評論

庆云县| 唐山市| 离岛区| 民丰县| 台州市| 新疆| 大冶市| 红桥区| 玛沁县| 肃南| 文成县| 红桥区| 清水河县| 山西省| 炎陵县| 平定县| 固阳县| 澳门| 阳朔县| 邵东县| 封开县| 镇宁| 六枝特区| 陈巴尔虎旗| 泸西县| 三亚市| 铜梁县| 孟州市| 英超| 吉安县| 定边县| 遵义市| 乐业县| 高碑店市| 同仁县| 济源市| 门源| 海安县| 新蔡县| 简阳市| 绥德县|