1 var _timeoutIDIndex = 0; 2 3 var TimeoutInfo = function TimeoutInfo(cb, delay, isRepeat, target, args) { 4 _classCallCheck(this, TimeoutInfo); 5 6 this.cb = cb; 7 this.id = ++_timeoutIDIndex; 8 this.start = performance.now(); 9 this.delay = delay; 10 this.isRepeat = isRepeat; 11 this.target = target; 12 this.args = args; 13 }; 14 15 var _timeoutInfos = {}; 16 17 function fireTimeout(nowMilliSeconds) { 18 var info; 19 20 for (var id in _timeoutInfos) { 21 info = _timeoutInfos[id]; 22 23 if (info && info.cb) { 24 if (nowMilliSeconds - info.start >= info.delay) { 25 // console.log(`fireTimeout: id ${id}, start: ${info.start}, delay: ${info.delay}, now: ${nowMilliSeconds}`); 26 if (typeof info.cb === 'string') { 27 Function(info.cb)(); 28 } else if (typeof info.cb === 'function') { 29 info.cb.apply(info.target, info.args); 30 } 31 32 if (info.isRepeat) { 33 info.start = nowMilliSeconds; 34 } else { 35 delete _timeoutInfos[id]; 36 } 37 } 38 } 39 } 40 } 41 42 function createTimeoutInfo(prevFuncArgs, isRepeat) { 43 var cb = prevFuncArgs[0]; 44 45 if (!cb) { 46 console.error("createTimeoutInfo doesn't pass a callback ..."); 47 return 0; 48 } 49 50 var delay = prevFuncArgs.length > 1 ? prevFuncArgs[1] : 0; 51 var args; 52 53 if (prevFuncArgs.length > 2) { 54 args = Array.prototype.slice.call(prevFuncArgs, 2); 55 } 56 57 var info = new TimeoutInfo(cb, delay, isRepeat, this, args); 58 _timeoutInfos[info.id] = info; 59 return info.id; 60 } 61 62 window.setTimeout = function (cb) { 63 return createTimeoutInfo(arguments, false); 64 }; 65 66 window.clearTimeout = function (id) { 67 delete _timeoutInfos[id]; 68 }; 69 70 window.setInterval = function (cb) { 71 return createTimeoutInfo(arguments, true); 72 }; 73 74 window.clearInterval = window.clearTimeout;
可以看到, setTimeout和setInterval都是创建了一个TimeOutInfo. 然后存放在_timeoutInfos数组中
执行了gameTick
function tick(nowMilliSeconds) { if (_firstTick) { _firstTick = false; if (window.onload) { var event = new Event('load'); event._target = window; window.onload(event); } } fireTimeout(nowMilliSeconds); for (var id in _requestAnimationFrameCallbacks) { _oldRequestFrameCallback = _requestAnimationFrameCallbacks[id]; if (_oldRequestFrameCallback) { delete _requestAnimationFrameCallbacks[id]; _oldRequestFrameCallback(nowMilliSeconds); } } flushCommands(); }
function flushCommands() { if (next_index > 0) { gl._flushCommands(next_index, buffer_data, commandCount); next_index = 0; commandCount = 0; } }