// ------------ local variables -------------------------------------------- //\r
// ------------------------------------------------------------------------- //\r
\r
-var X_Timer_SET_TIMEOUT = window.setTimeout,\r
+var X_Timer_now = Date.now || function(){ return +new Date; },\r
+\r
+ X_Timer_SET_TIMEOUT = window.setTimeout,\r
X_Timer_CLEAR_TIMEOUT = window.clearTimeout,\r
\r
X_Timer_REQ_ANIME_FRAME =\r
X_Timer_INTERVAL_TIME = 16,\r
X_Timer_TICKET_LIST = [],\r
X_Timer_removal = null,\r
+ X_Timer_skipUpdate = false,\r
X_Timer_uid = 0,\r
X_Timer_timerId = 0,\r
- X_Timer_next = 0,\r
- X_Timer_busyTimeout = false, \r
- X_Timer_endTime = 0, // iOS\r
+ X_Timer_busyTimeout = false,\r
+ X_Timer_timeStamp = 0, // setTimeout に登録した時間\r
+ X_Timer_waitTime = 0, // 待ち時間\r
\r
X_Timer_REQ_FRAME_LIST = [],\r
X_Timer_requestID = 0,\r
// ------------------------------------------------------------------------- //\r
X.Timer = {\r
\r
+ now : X_Timer_now,\r
+ \r
add : function( time, opt_count, args1, args2, args3 ){\r
var list = X_Timer_TICKET_LIST,\r
hash, obj;\r
opt_count = 0;\r
};\r
\r
- hash = X.Callback._classifyCallbackArgs( args1, args2, args3 );\r
+ hash = X_Callback_classifyCallbackArgs( args1, args2, args3 );\r
if( !hash ) return -1; // dev only\r
\r
if( !hash.k ) hash = { f : hash };\r
X_Timer_removal[ uid ] = true;\r
} else {\r
for( ; i; ){\r
- \r
if( ( q = list[ --i ] ).uid === uid ){\r
list.splice( i, 1 );\r
- ( /* q[ INDEX_COUNT ] <= next || */ l === 1 ) && X_Timer_update();\r
+ !X_Timer_skipUpdate && ( q.last <= X_Timer_waitTime || l === 1 ) && X_Timer_update();\r
break;\r
};\r
}; \r
var i = X_Timer_REQ_FRAME_LIST.length,\r
f;\r
i === 0 && ( X_Timer_requestID = X_Timer_REQ_ANIME_FRAME( X_Timer_onEnterFrame ) );\r
- f = X_Timer_REQ_FRAME_LIST[ i ] = X.Callback._classifyCallbackArgs( args1, args2, args3 );\r
+ f = X_Timer_REQ_FRAME_LIST[ i ] = X_Callback_classifyCallbackArgs( args1, args2, args3 );\r
return f.uid = ++X_Timer_uid;\r
}) :\r
(function( args1, args2, args3 ){\r
var i = X_Timer_REQ_FRAME_LIST.length,\r
f;\r
i === 0 && ( X_Timer_requestID = X.Timer.add( 0, 1, X_Timer_onEnterFrame ) );\r
- f = X_Timer_REQ_FRAME_LIST[ i ] = X.Callback._classifyCallbackArgs( args1, args2, args3 );\r
+ f = X_Timer_REQ_FRAME_LIST[ i ] = X_Callback_classifyCallbackArgs( args1, args2, args3 );\r
return f.uid = ++X_Timer_uid;\r
}),\r
\r
};\r
\r
function X_Timer_onTimeout(){\r
- var next = X_Timer_next,\r
+ var now = X_Timer_now(),\r
+ minus = ( ( now - X_Timer_timeStamp ) / X_Timer_INTERVAL_TIME | 0 ) || 1,\r
list = X_Timer_TICKET_LIST,\r
i = 0,\r
l = list.length,\r
- limit = X.getTime() + X_Timer_INTERVAL_TIME / 2,\r
+ limit = X_Timer_now() + X_Timer_INTERVAL_TIME / 2,\r
heavy,\r
q, f, c, r, uid;\r
\r
+ //console.log( '予定時間と発火時間の差:' + ( now - X_Timer_timeStamp - X_Timer_waitTime * X_Timer_INTERVAL_TIME ) + ' -:' + minus + ' next:' + X_Timer_waitTime );\r
+ \r
if( X_Timer_busyTimeout ){\r
- alert( 'busy!' );\r
+ alert( 'X_Timer_busyTimeout フラグが立ったまま!エラーの可能性' );\r
};\r
\r
X_Timer_busyTimeout = true;\r
\r
for( ; i < l; ++i ){\r
q = list[ i ];\r
- if( X_Timer_removal && X_Timer_removal[ q.uid ] ) continue;\r
- if( 0 < ( q.last -= next ) ) continue;\r
- if( heavy ){\r
- if( q.last <= 0 ) q.last = 1;\r
+ if(\r
+ ( X_Timer_removal && X_Timer_removal[ q.uid ] ) || // timerId は remove 登録されている\r
+ 0 < ( q.last -= minus ) || // 時間が経過していない\r
+ heavy && ( q.last = 1 ) // 時間は経過したが、ヘビーフラグが立っている\r
+ ){\r
continue;\r
};\r
c = q.count;\r
\r
if( q.k ){\r
- q.a = [];\r
- r = X.Callback._proxyCallback( q );\r
+ //q.a = [];\r
+ r = X_Callback_proxyCallback( q, [] );\r
} else {\r
r = q.f();\r
};\r
\r
//console.log( 'fire....' );\r
\r
- if( limit <= X.getTime() ){\r
+ if( limit <= X_Timer_now() ){\r
console.log( '******* heavy!' );\r
// 関数の実行に時間がかかる場合、次のタイミングに\r
heavy = true;\r
};\r
\r
- if( r & X.Callback.UN_LISTEN || c === 1 ){\r
+ if( r & X_Callback_UN_LISTEN || c === 1 ){\r
list.splice( i, 1 );\r
--i;\r
--l;\r
};\r
X_Timer_timerId = 0;\r
X_Timer_busyTimeout = false;\r
+ \r
if( X_Timer_removal ){\r
+ X_Timer_skipUpdate = true;\r
for( uid in X_Timer_removal ){\r
- X.Timer.remove( X_Timer_removal[ uid ] );\r
+ X.Timer.remove( uid );\r
};\r
+ X_Timer_skipUpdate = false;\r
X_Timer_removal = null;\r
};\r
X_Timer_update();\r
\r
n = list[ i - 1 ].last;\r
\r
- if( n < X_Timer_next || X_Timer_timerId === 0 ){\r
- X_Timer_timerId && X_Timer_CLEAR_TIMEOUT( X_Timer_timerId );\r
- X_Timer_timerId = X_Timer_SET_TIMEOUT( X_Timer_onTimeout, X_Timer_INTERVAL_TIME * n );\r
- X_Timer_endTime = X.getTime() + X_Timer_INTERVAL_TIME * n; // iOS\r
- X_Timer_next = n;\r
+ if( n < X_Timer_waitTime || X_Timer_timerId === 0 ){\r
+ if( X_Timer_timerId ){\r
+ X_Timer_CLEAR_TIMEOUT( X_Timer_timerId );\r
+ n -= ( X_Timer_now() - X_Timer_timeStamp ) / X_Timer_INTERVAL_TIME | 0;\r
+ 0 <= n || ( n = 0 ); // 負の数は 0 に\r
+ };\r
+ X_Timer_timeStamp = X_Timer_now();\r
+ X_Timer_timerId = X_Timer_SET_TIMEOUT( X_Timer_onTimeout, X_Timer_INTERVAL_TIME * n );\r
+ X_Timer_waitTime = n;\r
};\r
};\r
\r
+// 大きい -> 小さい\r
+function X_Timer_compareQueue( a, b ){\r
+ return a.last < b.last ? 1 : a.last === b.last ? 0 : -1;\r
+};\r
+\r
// http://havelog.ayumusato.com/develop/javascript/e528-ios6_scrolling_timer_notcall.html\r
// iOS6 スクロール中のタイマー発火絡みのバグ備忘\r
if( X.UA.iOS ){\r
window.addEventListener( 'scroll', function(){\r
- var last;\r
+ var last, now;\r
if( X_Timer_timerId ){\r
- window.clearTimeout( X_Timer_timerId );\r
- last = X_Timer_endTime - X.getTime();\r
+ X_Timer_CLEAR_TIMEOUT( X_Timer_timerId );\r
+ now = X_Timer_now();\r
+ last = X_Timer_timeStamp + X_Timer_INTERVAL_TIME * X_Timer_waitTime - now;\r
X_Timer_timerId = X_Timer_SET_TIMEOUT( X_Timer_onTimeout, 0 < last ? last : 0 );\r
+ // 更新\r
+ X_Timer_timeStamp = now;\r
+ X_Timer_waitTime = last / X_Timer_INTERVAL_TIME | 0;\r
};\r
});\r
};\r
function X_Timer_onEnterFrame( time ){\r
var list = X_Timer_REQ_FRAME_LIST,\r
l = list.length,\r
- i = 0, q, uid;\r
+ i = 0, q, uid, args;\r
\r
- time = time || X.getTime();\r
+ time = time || X_Timer_now();\r
X_Timer_busyOnFrame = true;\r
- // console.log( X.getTime() + ' , ' + time );\r
+ // console.log( X_Timer_now() + ' , ' + time );\r
for( ; i < l; ++i ){\r
q = list[ i ];\r
\r
if( X_Timer_removal && X_Timer_removal[ q.uid ] ) continue;\r
\r
if( q.k ){\r
- q.a = [ time ];\r
- X.Callback._proxyCallback( q );\r
+ X_Callback_proxyCallback( q, args || ( args = [ time ] ) );\r
} else {\r
q( time );\r
};\r
};\r
};\r
\r
-// 大きい -> 小さい\r
-function X_Timer_compareQueue( a, b ){\r
- return a.last < b.last ? 1 : a.last === b.last ? 0 : -1;\r
-};\r
-\r
-\r
console.log( 'X.Core.Timer' );\r