日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

nodejs源码_nodejs之setTimeout源码解析

發(fā)布時間:2025/3/8 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 nodejs源码_nodejs之setTimeout源码解析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

setTimeout是在系統(tǒng)啟動的時候掛載的全局函數(shù)。代碼在timer.js。

function setupGlobalTimeouts() {const timers = NativeModule.require('timers');global.clearImmediate = timers.clearImmediate;global.clearInterval = timers.clearInterval;global.clearTimeout = timers.clearTimeout;global.setImmediate = timers.setImmediate;global.setInterval = timers.setInterval;global.setTimeout = timers.setTimeout;}

我們先看一下setTimeout函數(shù)的代碼。

function setTimeout(callback, after, arg1, arg2, arg3) {if (typeof callback !== 'function') {throw new errors.TypeError('ERR_INVALID_CALLBACK');}var i, args;switch (arguments.length) {// fast casescase 1:case 2:break;case 3:args = [arg1];break;case 4:args = [arg1, arg2];break;default:args = [arg1, arg2, arg3];for (i = 5; i < arguments.length; i++) {// extend array dynamically, makes .apply run much faster in v6.0.0args[i - 2] = arguments[i];}break;}// 新建一個對象,保存回調(diào),超時時間等數(shù)據(jù),是超時哈希隊(duì)列的節(jié)點(diǎn)const timeout = new Timeout(callback, after, args, false, false);// 啟動超時器active(timeout);// 返回一個對象return timeout; }

其中Timeout函數(shù)在lib/internal/timer.js里定義。

function Timeout(callback, after, args, isRepeat, isUnrefed) {after *= 1; // coalesce to number or NaNthis._called = false;this._idleTimeout = after;this._idlePrev = this;this._idleNext = this;this._idleStart = null;this._onTimeout = null;this._onTimeout = callback;this._timerArgs = args;this._repeat = isRepeat ? after : null;this._destroyed = false;this[unrefedSymbol] = isUnrefed;this[async_id_symbol] = ++async_id_fields[kAsyncIdCounter];this[trigger_async_id_symbol] = getDefaultTriggerAsyncId();if (async_hook_fields[kInit] > 0) {emitInit(this[async_id_symbol],'Timeout',this[trigger_async_id_symbol],this);} }

由代碼可知,首先創(chuàng)建一個保存相關(guān)信息的對象,然后執(zhí)行active函數(shù)。

const active = exports.active = function(item) {// 插入一個超時對象到超時隊(duì)列insert(item, false); } function insert(item, unrefed, start) {// 超時時間const msecs = item._idleTimeout;if (msecs < 0 || msecs === undefined) return;// 如果傳了start則計算是否超時時以start為起點(diǎn),否則取當(dāng)前的時間if (typeof start === 'number') {item._idleStart = start;} else {item._idleStart = TimerWrap.now();}// 哈希隊(duì)列const lists = unrefed === true ? unrefedLists : refedLists;var list = lists[msecs];// 沒有則新建一個隊(duì)列if (list === undefined) {debug('no %d list was found in insert, creating a new one', msecs);lists[msecs] = list = new TimersList(msecs, unrefed);}...// 把超時節(jié)點(diǎn)插入超時隊(duì)列L.append(list, item);assert(!L.isEmpty(list)); // list is not empty }

從上面的代碼可知,active一個定時器實(shí)際上是把新建的timeout對象掛載到一個哈希隊(duì)列里。我們看一下這時候的內(nèi)存視圖。

當(dāng)我們創(chuàng)建一個timerList的是時候,就會關(guān)聯(lián)一個底層的定時器,執(zhí)行setTimeout時傳進(jìn)來的時間是一樣的,都會在一條隊(duì)列中進(jìn)行管理,該隊(duì)列對應(yīng)一個定時器,當(dāng)定時器超時的時候,就會在該隊(duì)列中找出超時節(jié)點(diǎn)。下面我們看一下new TimeWraper的時候發(fā)生了什么。

TimerWrap(Environment* env, Local<Object> object) : HandleWrap(env, object,reinterpret_cast<uv_handle_t*>(&handle_),AsyncWrap::PROVIDER_TIMERWRAP) {int r = uv_timer_init(env->event_loop(), &handle_);CHECK_EQ(r, 0);}

其實(shí)就是初始化了一個libuv的uv_timer_t結(jié)構(gòu)體。然后接著start函數(shù)做了什么操作。

static void Start(const FunctionCallbackInfo<Value>& args) {TimerWrap* wrap = Unwrap<TimerWrap>(args.Holder());CHECK(HandleWrap::IsAlive(wrap));int64_t timeout = args[0]->IntegerValue();int err = uv_timer_start(&wrap->handle_, OnTimeout, timeout, 0);args.GetReturnValue().Set(err);}

就是啟動了剛才初始化的定時器。并且設(shè)置了超時回調(diào)函數(shù)是OnTimeout。這時候,就等定時器超時,然后執(zhí)行OnTimeout函數(shù)。所以我們繼續(xù)看該函數(shù)的代碼。

const uint32_t kOnTimeout = 0;static void OnTimeout(uv_timer_t* handle) {TimerWrap* wrap = static_cast<TimerWrap*>(handle->data);Environment* env = wrap->env();HandleScope handle_scope(env->isolate());Context::Scope context_scope(env->context());wrap->MakeCallback(kOnTimeout, 0, nullptr);}

OnTimeout函數(shù)繼續(xù)調(diào)kOnTimeout,但是該變量在time_wrapper.c中是一個整形,這是怎么回事呢?這時候需要回lib/timer.js里找答案。

const kOnTimeout = TimerWrap.kOnTimeout | 0; // adds listOnTimeout to the C++ object prototype, as // V8 would not inline it otherwise. // 在TimerWrap中是0,給TimerWrap對象掛一個超時回調(diào),每次的超時都會執(zhí)行該回調(diào) TimerWrap.prototype[kOnTimeout] = function listOnTimeout() {// 拿到該底層定時器關(guān)聯(lián)的超時隊(duì)列,看TimersListvar list = this._list;var msecs = list.msecs;//if (list.nextTick) {list.nextTick = false;process.nextTick(listOnTimeoutNT, list);return;}debug('timeout callback %d', msecs);var now = TimerWrap.now();debug('now: %d', now);var diff, timer;// 取出隊(duì)列的尾節(jié)點(diǎn),即最先插入的節(jié)點(diǎn),最可能超時的,TimeOut對象while (timer = L.peek(list)) {diff = now - timer._idleStart;// Check if this loop iteration is too early for the next timer.// This happens if there are more timers scheduled for later in the list.// 最早的節(jié)點(diǎn)的消逝時間小于設(shè)置的時間,說明還沒超時,并且全部節(jié)點(diǎn)都沒超時,直接返回if (diff < msecs) {// 算出最快超時的節(jié)點(diǎn)還需要多長時間超時var timeRemaining = msecs - (TimerWrap.now() - timer._idleStart);if (timeRemaining < 0) {timeRemaining = 1;}// 重新設(shè)置超時時間this.start(timeRemaining);debug('%d list wait because diff is %d', msecs, diff);return;}// The actual logic for when a timeout happens.// 當(dāng)前節(jié)點(diǎn)已經(jīng)超時 L.remove(timer);assert(timer !== L.peek(list));if (!timer._onTimeout) {if (async_hook_fields[kDestroy] > 0 && !timer._destroyed &&typeof timer[async_id_symbol] === 'number') {emitDestroy(timer[async_id_symbol]);timer._destroyed = true;}continue;}// 執(zhí)行超時處理tryOnTimeout(timer, list);}

由上可知,TimeWrapper.c里的kOnTimeout字段已經(jīng)被改寫成一個函數(shù),所以底層的定時器超時時會執(zhí)行上面的代碼,即從定時器隊(duì)列中找到超時節(jié)點(diǎn)執(zhí)行,直到遇到第一個未超時的節(jié)點(diǎn),然后重新設(shè)置超時時間。再次啟動定時器。

總結(jié)

以上是生活随笔為你收集整理的nodejs源码_nodejs之setTimeout源码解析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 色婷婷视频网 | 中文一二三区 | 丰满的女邻居 | 久久久久在线视频 | 少妇福利在线 | 亚洲一级在线观看 | 蜜臀av无码精品人妻色欲 | 欧美激情视频一区二区 | 久色资源 | 欧美色v | 免费国产小视频 | 欧洲亚洲成人 | 男人和女人日b视频 | 视色影院 | 台湾佬av | 两口子交换真实刺激高潮 | 王者后宫yin肉h文催眠 | www.国产区 | 欧美精品91| 久久精品一区二区三区不卡牛牛 | 亚洲伦理网站 | 日本伊人久久 | 三级亚洲欧美 | 国产99在线播放 | 国产黄色网络 | 欧洲在线观看 | 99精品一区 | 亚洲区一区二 | 日本草逼视频 | 天天色网站 | 欧美性生交xxxxx久久久 | 精品人妻一区二区三区麻豆91 | 中文字幕亚洲欧美日韩在线不卡 | 夜夜骚视频 | 中文成人在线 | 精品96久久久久久中文字幕无 | 久久在线| 4438x全国最大成人网 | 成人性做爰aaa片免费看不忠 | 日韩插插插| 免费裸体视频网站 | 一区二区中文在线 | 能在线观看的av | 很色的网站 | 极品尤物一区二区三区 | 日韩天堂在线视频 | 天天噜夜夜噜 | 精品国产乱 | 亚洲高清不卡 | 人妻少妇一区二区 | 蕾丝视频污 | 日韩区一区二 | 国产精品久久久久久妇女 | 草草影院第一页 | 69精品丰满人妻无码视频a片 | 第一章豪妇荡乳黄淑珍 | 国产福利免费看 | 国产91在线亚洲 | 久久精品亚洲a | 欧美午夜不卡 | 欧美激情在线免费 | 亚洲成a人片777777久久 | 午夜啪啪福利视频 | 尤物视频一区 | 在线看的免费网站 | 色一情一乱一伦 | 1000部国产精品成人观看 | 91网址在线 | 日韩国产免费 | 69中国xxxxxxxxx69| 国产在线视频卡一卡二 | 亚洲AV无码精品国产 | 九色精品在线 | 亚洲欧美日韩国产成人精品影院 | 国产xxxxx| 免费黄色视屏 | 日韩精品欧美 | 日韩高清中文字幕 | a级黄色片| 国产日韩av一区二区 | 亚洲一级电影 | 国产精品久久久久久久久久久久久久久久 | 亚洲欧美成人综合 | 欧美美女一区二区三区 | 污污小视频 | 日日夜夜超碰 | 久久久久久国产精品免费 | 国产学生美女无遮拦高潮视频 | 亚洲国产视频一区二区 | 亚洲国产欧美一区二区三区深喉 | 国产亚洲精品自拍 | 黄色高清在线观看 | 香蕉尹人 | 国产福利一区二区三区 | 91国模| 日本电影一区二区三区 | 精品一区二区三区入口 | 中国av一区二区三区 | 男生和女生差差的视频 |