-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathsetZeroTimeout.js
55 lines (51 loc) · 1.9 KB
/
setZeroTimeout.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/**
* If the browser is capable, tries zero timeout via postMessage (setTimeout can't go faster than 10ms).
* Otherwise, it falls back to setTimeout(fn, delay) (which is the same as setTimeout(fn, 10) if under 10).
* @function
* @param {Function} fn
* @param {int} delay
* @example setZeroTimeout(function () { $.ajax('about:blank'); }, 0);
*/
var setZeroTimeout = (function (w) {
if (w.postMessage) {
var timeouts = [],
msg_name = 'asc0tmot',
// Like setTimeout, but only takes a function argument. There's
// no time argument (always zero) and no arguments (you have to
// use a closure).
_postTimeout = function (fn) {
timeouts.push(fn);
postMessage(msg_name, '*');
},
_handleMessage = function (event) {
if (event.source == w && event.data == msg_name) {
if (event.stopPropagation) {
event.stopPropagation();
}
if (timeouts.length) {
try {
timeouts.shift()();
} catch (e) {
// Throw in an asynchronous closure to prevent setZeroTimeout from hanging due to error
setTimeout((function (e) {
return function () {
throw e.stack || e;
};
}(e)), 0);
}
}
if (timeouts.length) { // more left?
postMessage(msg_name, '*');
}
}
};
if (w.addEventListener) {
addEventListener('message', _handleMessage, true);
return _postTimeout;
} else if (w.attachEvent) {
attachEvent('onmessage', _handleMessage);
return _postTimeout;
}
}
return setTimeout;
}(window));