真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

nodejs的定時(shí)器怎么用

這篇文章給大家分享的是有關(guān)nodejs的定時(shí)器怎么用的內(nèi)容。小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧。

創(chuàng)新互聯(lián)建站專業(yè)為企業(yè)提供景泰網(wǎng)站建設(shè)、景泰做網(wǎng)站、景泰網(wǎng)站設(shè)計(jì)、景泰網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)與制作、景泰企業(yè)網(wǎng)站模板建站服務(wù),10余年景泰做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。

看一下定時(shí)器的使用。

int main() 

  v_timer_t once;

  uv_timer_init(uv_default_loop(), &once);

  uv_timer_start(&once, once_cb, 10, 0);

  uv_run(uv_default_loop(), UV_RUN_DEFAULT);

  return 0;

}

我們從uv_timer_init函數(shù)開(kāi)始分析。

// 初始化uv_timer_t結(jié)構(gòu)體

int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) {

  uv__handle_init(loop, (uv_handle_t*)handle, UV_TIMER);

  handle->timer_cb = NULL;

  handle->repeat = 0;

  return 0;

}

init函數(shù)和其他階段的init函數(shù)一樣,初始化handle和私有的一些字段。接著我們看start函數(shù)。該函數(shù)是啟動(dòng)一個(gè)定時(shí)器(省略部分代碼)。

// 啟動(dòng)一個(gè)計(jì)時(shí)器

int uv_timer_start(

   uv_timer_t* handle,

   uv_timer_cb cb,

   uint64_t timeout,

   uint64_t repeat

 ) {

  uint64_t clamped_timeout;

  // 重新執(zhí)行start的時(shí)候先把之前的停掉

  if (uv__is_active(handle))

    uv_timer_stop(handle);

  // 超時(shí)時(shí)間,為絕對(duì)值

  clamped_timeout = handle->loop->time + timeout;

  // 初始化回調(diào),超時(shí)時(shí)間,是否重復(fù)計(jì)時(shí),賦予一個(gè)獨(dú)立無(wú)二的id

  handle->timer_cb = cb;

  handle->timeout = clamped_timeout;

  handle->repeat = repeat;

  /* start_id is the second index to be compared in uv__timer_cmp() */

  handle->start_id = handle->loop->timer_counter++;

  // 插入最小堆

  heap_insert(timer_heap(handle->loop),

              (struct heap_node*) &handle->heap_node,

              timer_less_than);

  // 激活該handle

  uv__handle_start(handle);

  return 0;

}

start函數(shù)首先初始化handle里的某些字段,包括超時(shí)回調(diào),是否重復(fù)啟動(dòng)定時(shí)器、超時(shí)的絕對(duì)時(shí)間等。接著把handle節(jié)點(diǎn)插入到最小堆中。最后給這個(gè)handle打上標(biāo)記,激活這個(gè)handle。這時(shí)候的結(jié)構(gòu)體如下。

這時(shí)候到了事件循環(huán)的timer階段。

// 找出已經(jīng)超時(shí)的節(jié)點(diǎn),并且執(zhí)行里面的回調(diào)

void uv__run_timers(uv_loop_t* loop) {

  struct heap_node* heap_node;

  uv_timer_t* handle;

  for (;;) {

    heap_node = heap_min(timer_heap(loop));

    if (heap_node == NULL)

      break;

    handle = container_of(heap_node, uv_timer_t, heap_node);

    // 如果當(dāng)前節(jié)點(diǎn)的時(shí)間大于當(dāng)前時(shí)間則返回,說(shuō)明后面的節(jié)點(diǎn)也沒(méi)有超時(shí)

    if (handle->timeout > loop->time)

      break;

    // 移除該計(jì)時(shí)器節(jié)點(diǎn),重新插入最小堆,如果設(shè)置了repeat的話

    uv_timer_stop(handle);

    uv_timer_again(handle);

    // 執(zhí)行超時(shí)回調(diào)

    handle->timer_cb(handle);

  }

}

libuv在每次事件循環(huán)開(kāi)始的時(shí)候都會(huì)緩存當(dāng)前的時(shí)間,在整個(gè)一輪的事件循環(huán)中,使用的都是這個(gè)緩存的時(shí)間。緩存了當(dāng)前最新的時(shí)間后,就執(zhí)行uv__run_timers,該函數(shù)的邏輯很明了,就是遍歷最小堆,找出當(dāng)前超時(shí)的節(jié)點(diǎn)。因?yàn)槎训男再|(zhì)是父節(jié)點(diǎn)肯定比孩子小。所以如果找到一個(gè)節(jié)點(diǎn),他沒(méi)有超時(shí),則后面的節(jié)點(diǎn)也不會(huì)超時(shí)。對(duì)于超時(shí)的節(jié)點(diǎn)就知道他的回調(diào)。執(zhí)行完回調(diào)后,還有兩個(gè)關(guān)鍵的操作。第一就是stop,第二就是again。

// 停止一個(gè)計(jì)時(shí)器

int uv_timer_stop(uv_timer_t* handle) {

  if (!uv__is_active(handle))

    return 0;

  // 從最小堆中移除該計(jì)時(shí)器節(jié)點(diǎn)

  heap_remove(timer_heap(handle->loop),

              (struct heap_node*) &handle->heap_node,

              timer_less_than);

  // 清除激活狀態(tài)和handle的active數(shù)減一

  uv__handle_stop(handle);

  return 0;

}

stop的邏輯很簡(jiǎn)單,其實(shí)就是把handle從二叉堆中刪除。并且取消激活狀態(tài)。那么againt又是什么呢?again是為了支持setInterval這種場(chǎng)景。

// 重新啟動(dòng)一個(gè)計(jì)時(shí)器,需要設(shè)置repeat標(biāo)記 

int uv_timer_again(uv_timer_t* handle) {

  // 如果設(shè)置了repeat標(biāo)記說(shuō)明計(jì)時(shí)器是需要重復(fù)觸發(fā)的

  if (handle->repeat) {

    // 先把舊的計(jì)時(shí)器節(jié)點(diǎn)從最小堆中移除,然后再重新開(kāi)啟一個(gè)計(jì)時(shí)器

    uv_timer_stop(handle);

    uv_timer_start(handle, handle->timer_cb, handle->repeat, handle->repeat);

  }

  return 0;

}

如果handle設(shè)置了repeat標(biāo)記,則該handle在超時(shí)后,每repeat的時(shí)間后,就會(huì)繼續(xù)執(zhí)行超時(shí)回調(diào)。對(duì)于setInterval,就是超時(shí)時(shí)間是x,每x的時(shí)間后,執(zhí)行回調(diào)。這就是nodejs里定時(shí)器的底層原理。但nodejs不是每次調(diào)setTimeout的時(shí)候都往最小堆插入一個(gè)節(jié)點(diǎn)。nodejs里,只有一個(gè)關(guān)于uv_timer_s的handle。他在js層維護(hù)了一個(gè)數(shù)據(jù)結(jié)構(gòu),每次計(jì)算出最早到期的節(jié)點(diǎn),然后修改handle的超時(shí)時(shí)間。具體原理在之前的一篇文章已經(jīng)分析過(guò)。

timer階段和poll io階段也有一些聯(lián)系,因?yàn)閜oll io可能會(huì)導(dǎo)致主線程阻塞,為了保證主線程可以盡快執(zhí)行定時(shí)器的回調(diào),poll io不能一直阻塞,所以這時(shí)候,阻塞的時(shí)長(zhǎng)就是最快到期的定時(shí)器節(jié)點(diǎn)的時(shí)長(zhǎng)。

感謝各位的閱讀!關(guān)于“nodejs的定時(shí)器怎么用”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!


新聞名稱:nodejs的定時(shí)器怎么用
標(biāo)題來(lái)源:http://weahome.cn/article/poeois.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部