当前位置: 首页 > news >正文

win 2012 iis 默认网站网络公司市值最新排名

win 2012 iis 默认网站,网络公司市值最新排名,扬州做网站的科技公司,微信小程序开发要多少钱深入了解setTimeout源码之前#xff0c;本有两个选择。一是通过chromium源码分析#xff0c;二是通过Node.js源码分析。后来发现第一种方案的源码获取成本太大#xff0c;于是从Node官网获取了几十兆的代码用来了解。 当前的Node版本为#xff1a;v10.16.0 setTimeout方法定…深入了解setTimeout源码之前本有两个选择。一是通过chromium源码分析二是通过Node.js源码分析。后来发现第一种方案的源码获取成本太大于是从Node官网获取了几十兆的代码用来了解。 当前的Node版本为v10.16.0 setTimeout方法定义于timers.js文件中源码整体如下 function setTimeout(callback, after, arg1, arg2, arg3) {// 基础校验if (typeof callback ! function) {throw new 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;}// 新建Timeout对象const timeout new Timeout(callback, after, args, false, false);active(timeout);// 最后返回Timeout对象return timeout; }Timeout构造函数内部如下 // Timer constructor function. // The entire prototype is defined in lib/timers.js function Timeout(callback, after, args, isRepeat, isUnrefed) {after * 1; // coalesce to number or NaNif (!(after 1 after TIMEOUT_MAX)) {if (after TIMEOUT_MAX) {process.emitWarning(${after} does not fit into a 32-bit signed integer. \nTimeout duration was set to 1.,TimeoutOverflowWarning);}after 1; // schedule on next tick, follows browser behavior}this._called false;this._idleTimeout after;this._idlePrev this;this._idleNext this;this._idleStart null;// this must be set to null first to avoid function tracking// on the hidden class, revisit in V8 versions after 6.2this._onTimeout null;this._onTimeout callback;this._timerArgs args;this._repeat isRepeat ? after : null;this._destroyed false;this[unrefedSymbol] isUnrefed;initAsyncResource(this, Timeout); }我们这里分析只关注两个参数1.callback, 2.after this._idleTimeout after;this._onTimeout callback;基本初始化完成进入active方法。active方法的item参数为新new的Timeout对象。 // Schedule or re-schedule a timer. // The item must have been enroll()d first. const active exports.active function(item) {insert(item, false); };进入insert方法item Timeout对象, unrefed false, start undefined. // The underlying logic for scheduling or re-scheduling a timer. // // Appends a timer onto the end of an existing timers list, or creates a new // TimerWrap backed list if one does not already exist for the specified timeout // duration. function insert(item, unrefed, start) { // timeout, false // 对after做校验const msecs item._idleTimeout;if (msecs 0 || msecs undefined) return;if (typeof start number) {item._idleStart start;} else {item._idleStart TimerWrap.now();}const lists unrefed true ? unrefedLists : refedLists;// Use an existing list if there is one, otherwise we need to make a new one.var list lists[msecs];if (list undefined) {debug(no %d list was found in insert, creating a new one, msecs);lists[msecs] list new TimersList(msecs, unrefed);}if (!item[async_id_symbol] || item._destroyed) {item._destroyed false;initAsyncResource(item, Timeout);}L.append(list, item); // list timerlist, item timeout, 增加一个节点在队列中节点类型不同。assert(!L.isEmpty(list)); // list is not empty }TimerWrap.now()方法返回的应当是当前的时间具体的执行代码为 static void Now(const FunctionCallbackInfoValue args) {Environment* env Environment::GetCurrent(args);args.GetReturnValue().Set(env-GetNow());}这时Timeout对象有三个关键属性 item._idleTimeout after; // 延迟多少秒执行item._onTimeout callback; // 延迟执行回调函数item._idleStart TimerWrap.now(); // 当下时间然后进行到lists[after] refedLists[after] list new TimersList(after, false); 也就是说refedLists对象的after属性对应一个TimersList对象而refedLists对象是全局的。 function TimersList(msecs, unrefed) {this._idleNext this; // Create the list with the linkedlist properties tothis._idlePrev this; // prevent any unnecessary hidden class changes.this._unrefed unrefed;this.msecs msecs;const timer this._timer new TimerWrap();timer._list this;if (unrefed true)timer.unref();timer.start(msecs); }可以将TimersList对象视作为一个双向链表节点它内部有指向上下节点的指针当一个节点新建时这个节点的的上下节点会指向自己。节点的内容为 this.msecs after;this._timer new TimerWrap(); // 这里的TimerWrap为一个Native对象timer._list this;最后到timer.start(after)它的函数内部如下 static void Start(const FunctionCallbackInfoValue args) {TimerWrap* wrap;ASSIGN_OR_RETURN_UNWRAP(wrap, args.Holder());CHECK(HandleWrap::IsAlive(wrap));int64_t timeout args[0]-IntegerValue(); // 这里的timeout为js代码传入的afterint err uv_timer_start(wrap-handle_, OnTimeout, timeout, 0);args.GetReturnValue().Set(err);}这里关键的地方是uv_timer_start方法的内部如下 int uv_timer_start(uv_timer_t* handle,uv_timer_cb cb,uint64_t timeout,uint64_t repeat) {uint64_t clamped_timeout;if (cb NULL)return UV_EINVAL;if (uv__is_active(handle))uv_timer_stop(handle);// 这里是关键。clamped_timeout的值等于当前时间加上未来要执行的时间clamped_timeout handle-loop-time timeout;if (clamped_timeout timeout)clamped_timeout (uint64_t) -1;handle-timer_cb cb;handle-timeout clamped_timeout; // 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);uv__handle_start(handle);return 0; }这里我关注的是传入参数是怎么被操作的 handle-timer_cb cb;handle-timeout clamped_timeout;好到这里设置完成我们回到insert方法内部继续向下继续执行 L.append(list, item); // list timerlist, item timeout, 增加一个节点在队列中节点类型不同。append方法将item追加到了list中。list对象是一个由item节点组成的双向链表。然后到这里添加结束。 你可能会疑惑到这里就结束了其实过程中有很多细节被我们忽略了不过没关系。既然L.append用来追加节点那它一定要取出节点我们从上下文可知 listOnTimeout方法中取出了这个节点这个过程后面再涉及 function listOnTimeout(handle, now) {const list handle._list;const msecs list.msecs;debug(timeout callback %d, msecs);debug(now: %d, now);var diff, timer;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.if (diff msecs) {var timeRemaining msecs - (TimerWrap.now() - timer._idleStart);if (timeRemaining 0) {timeRemaining 1;}handle.start(timeRemaining);debug(%d list wait because diff is %d, msecs, diff);return true;}// The actual logic for when a timeout happens.L.remove(timer);assert(timer ! L.peek(list));if (!timer._onTimeout) {if (destroyHooksExist() !timer._destroyed typeof timer[async_id_symbol] number) {emitDestroy(timer[async_id_symbol]);timer._destroyed true;}continue;}tryOnTimeout(timer);}// If L.peek(list) returned nothing, the list was either empty or we have// called all of the timer timeouts.// As such, we can remove the list and clean up the TimerWrap C handle.debug(%d list empty, msecs);assert(L.isEmpty(list));// Either refedLists[msecs] or unrefedLists[msecs] may have been removed and// recreated since the reference to list was created. Make sure theyre// the same instance of the list before destroying.if (list._unrefed true list unrefedLists[msecs]) {delete unrefedLists[msecs];} else if (list refedLists[msecs]) {delete refedLists[msecs];}// Do not close the underlying handle if its ownership has changed// (e.g it was unrefed in its callback).if (!handle[owner_symbol])handle.close();return true; }listOnTimeout方法其实是整个JS层处理队列事件的核心。方法内部的handle对象实为TimerWrap。handle._list为TimersList。方法内的msecs为after。接下来while不断从TimersList中取timer。peek总是返回队首的数据。 然后到了关键处理阶段 diff now - timer._idleStart; // 计算方法执行时的差额// 如果时间还不到则进行if (diff msecs) {var timeRemaining msecs - (TimerWrap.now() - timer._idleStart);if (timeRemaining 0) {timeRemaining 1;}// 计算出剩余时间再次执行Native的start方法。handle.start(timeRemaining);debug(%d list wait because diff is %d, msecs, diff);return true;}handle.start方法的内部如下 static void Start(const FunctionCallbackInfoValue args) {TimerWrap* wrap;ASSIGN_OR_RETURN_UNWRAP(wrap, 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);}这时在执行start方法时就是一个after距离真正执行的剩余时间再次执行uv_timer_start方法 还记得上文中提到的这段代码吗这段代码位于uv_timer_start方法内。 handle-timer_cb cb;handle-timeout clamped_timeout;刚刚我们并没有继续深究现在不得不深究一下。 上面说到timeout被赋值了那一定有地方再取出它进行执行。通过上下文可知 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);// 这里为处理的关键。if (handle-timeout loop-time)break;uv_timer_stop(handle);uv_timer_again(handle);handle-timer_cb(handle);} }uv__run_timers是一个无限循环的方法内部永远在循环执行timer_cb方法。还记得上文中提到的clamped_timeout吗如果clamped_timeout为任务触发的时间这里的无限循环一直在判断时间是否到期如果到期了则会向下执行否则一直循环。 这个方法是如何被触发的我们暂时不在这里深究。 我们从上文的代码可以知道上文中的timer_cb是OnTimeout方法它的内部实现如下 static void OnTimeout(uv_timer_t* handle) {TimerWrap* wrap static_castTimerWrap*(handle-data);Environment* env wrap-env();HandleScope handle_scope(env-isolate());Context::Scope context_scope(env-context());MaybeLocalValue ret;LocalValue args[1];do {// 这里是关键所在args[0] env-GetNow(); // 获取当前时间ret wrap-MakeCallback(env-timers_callback_function(), 1, args); // 执行调用} while ((ret.IsEmpty() || ret.ToLocalChecked()-IsUndefined()) !env-tick_info()-has_thrown() env-can_call_into_js() wrap-object()-Get(env-context(),env-owner_symbol()).ToLocalChecked()-IsUndefined());}这里的timers_callback_function()为js层传入的processTimers方法设置的代码位于lib/timers.js文件中 const [immediateInfo, toggleImmediateRef] setupTimers(processImmediate, processTimers);processTimers内部如下 function processTimers(now) {if (this[owner_symbol])return unrefdHandle(this[owner_symbol], now);return listOnTimeout(this, now); }到这里是不是见过listOnTimeout方法没错我们回到了listOnTimeout方法调用处。这个从listOnTimeout方法到listOnTimeout方法会不断循环直到if (diff msecs) 条件不成立。也就是说当条件成立时才会继续执行。 真正的业务回调代码如下 // 将这次的timer任务从队列中取出L.remove(timer);assert(timer ! L.peek(list));// 这里不成立if (!timer._onTimeout) {if (destroyHooksExist() !timer._destroyed typeof timer[async_id_symbol] number) {emitDestroy(timer[async_id_symbol]);timer._destroyed true;}continue;}// 关键在于这里tryOnTimeout(timer);function tryOnTimeout(timer, start) {timer._called true;const timerAsyncId (typeof timer[async_id_symbol] number) ?timer[async_id_symbol] : null;var threw true;if (timerAsyncId ! null)emitBefore(timerAsyncId, timer[trigger_async_id_symbol]);try {ontimeout(timer, start);threw false;} finally {if (timerAsyncId ! null) {if (!threw)emitAfter(timerAsyncId);if ((threw || !timer._repeat) destroyHooksExist() !timer._destroyed) {emitDestroy(timerAsyncId);timer._destroyed true;}}} }这里的关键在于ontimeout方法该方法内部实现如下: function ontimeout(timer, start) {const args timer._timerArgs;if (typeof timer._onTimeout ! function)return Promise.resolve(timer._onTimeout, args[0]);if (start undefined timer._repeat)start TimerWrap.now();if (!args)timer._onTimeout();elseReflect.apply(timer._onTimeout, timer, args);if (timer._repeat)rearm(timer, start); }上面的方法执行javascript timer._onTimeout();这里是真正的回调执行。 至此一个普通的setTimeout方法执行完毕。 最后总结一下调用流程图
http://www.pierceye.com/news/580846/

相关文章:

  • 千万pv网站开发成本招聘网站数建设
  • 吐鲁番大型网站建设平台找客户去哪个平台
  • 权威网站有哪些给个网站可以在线
  • 优化网站专题北京海淀网站建设公司
  • 广州网站快速排名网站维护正常要多久
  • 建网站 选安全甘肃做网站价格
  • 微信公众管理平台有必要买优化大师会员吗
  • 家居网站建设素材腾讯adq广告平台
  • 响应式网站 图片居中门户网站样式
  • 潍坊网站排名推广北京建设高端网站的
  • 广东省住房和建设网站鹤壁市建设局网站
  • 北京网站建设报价明细手机网站网站开发流程
  • 三合一网站模板如何看网站是html几代做的
  • 如何设置自己的网站网站建设的常用词
  • 甘肃网站开发冷色调网站
  • 用cdr做网站设计尺寸要多少网站如何做实名验证码
  • 比较好的设计网站wordpress主题代码哪里
  • 专门学习网站建设读什么专业南山网站设计公司
  • 专业网站设计模板深圳最专业的高端网站建设
  • cc域名做网站怎么样无锡个人网站建设
  • 网站模板设计报价单小学网站建设设计方案
  • 二级域名网站怎么投广告wordpress自定义输入
  • su域名注册如何做360网站优化
  • 企业网站空间不足怎么办incapsula wordpress
  • 网站建设 镇江万达wordpress简
  • 做p2p理财网站开发公司销售人员竞聘演讲稿
  • 建设网站广州唯品会网站架构
  • 网站开发的国内外研究现状家庭装潢设计
  • 安卓从网站获取视频怎么做有没有做网站的公司
  • 网站设计计划书的内容如何做1个手机网站