Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
setTimeout(function(){
clearInterval();
setInterval(arguments.callee, 12);
setTimeout(arguments.callee, 10);
/* Какой-то большой участок кода... */
}, 10);
setInterval(function(){
clearTimeout();
setTimeout(arguments.callee, 10);
/* Какой-то большой участок кода... */
}, 12);
window (но я сам точно не знаю, есть предположение, что от браузера к браузеру будет варьироваться)window вроде navigator, если верить этой схемеtop
Refers to the window object of the page at the top of the frames hierarchy.
AndrewSuminИз-за того, что JavaScript может исполнять одновременно только один кусок кода (так как является однопоточным по самой своей структуре), каждый из этих блоков «блокирует» выполнение других асинхронных событий. Это означает, что при возникновении асинхронного события (например, клика мыши, срабатывания таймера или завершения XMLHttpRequest), его исполнение отодвигается дальше по оси времени и будет выполнено позже (точный процесс задержек в данном случае обусловлен отличительными особенностями конкретного браузера, поэтому мы рассматриваем такую упрощенную картину).
Для начала, внутри первого блока JavaScript устанавливаются два таймера: на 10мс через setTimeout и на 10мс через setInterval. Из-за того, как и где этот таймер был выставлен (было выставлено 2 таймера, однако, тут и далее речь идет про один; почему так — объясняется чуть дальше), он в действительности срабатывает до того, как завершается первый блок кода. Заметим, однако, что таймер исполнится не сразу после окончания этого блока, а через некоторое время (это невозможно по причине наличия других потоков, состояние которых также нужно проверить). Вместо этого задержанная в выполнении функция посылается в очередь для выполнения в следующий свободный момент.
Внутренние обработчики JavaScript, связанные с этим асинхронным событием (мы никогда не знаем, когда именно пользователь нажмет на кнопку мыши, поэтому и рассматриваем это событие как асинхронное), не могут быть выполнены сразу после данного события, так как и выставленный таймер, поэтому они откладываются до более удобного случая в будущем.
После того как наш первый блок JavaScript-кода закончит исполнение (наконец-то!), браузер тут же смотрит в очередь: что должно быть выполнено в следующий момент? В этом случае и клик мыши, и таймер ждут своей очереди на выполнение. Браузер берет один из них (обработчик клика мыши) и немедленно запускает его выполнение. Таймер будет ждать следующего удобного момент для того, чтобы выполниться.
Заметим, что обработчик клика мыши выполняется прежде, чем первый таймер. из-за этого выполнение таймера откладывается. Однако, стоит обратить внимание, Что при последующем срабатывании того же таймера (interval), он сбрасывается. Если вы думали, что все вызовы таймера, выставленного с определенным интервалом, создадут своеобразную очередь после выполнения большого блока кода безо всяких промежутков между собой, то вы ошибались. Вместо этого браузеры предпочитают просто ждать, пока не останется других, отложенных с помощью таймера, функций (в данном случае выставленных на выполнение через интервал), перед добавлением в их очередь выполнения.
(function () {
var i = 0, d = new Date;
document.onclick = function () {
var s = new Date;
while ((new Date) - s < 2000);
console.log((new Date) - d);
if (i == 0) {
var id = setInterval(function () {
if (i > 5) {
return clearInterval(id);
};
console.log(i++ + ': ' + ((new Date) - d));
}, 1000);
};
};
}());
5795
7800
9805
11810
13815
16735
21842
24050
0: 24141
1: 24524
2: 24564
3: 24583
4: 24742
5: 24819
5795
7800
0: 8000
9805
11810
13815
16735
21842
24050
1: 24524
2: 24564
3: 24583
4: 24742
5: 24819
onlick, это до условия и само выставление интервала)мало того, что не создает анонимную функцию в качестве обработчика события, так еще и не создает анонимную функцию для выполнения с определенным интервалом? Так Ваши слова понимать?
document.onclick = function () {
...
setInterval(function(){...},1000);
...
};
i увеличилась. Если Вам интересно, чему равна i при каждом установлении setTimeout можете проследить. Однако, лог консоли красноречиво об этом говорит.
window.onload = function () {
var numberOfCalls = 0;
/* numberOfCalls - numeration of function' calls (so no one won't be lost)
!!! it should be equaled always to zero
*/
var callsLimit = 5; // the limit of function calls
var interval = 1000; // desirable interval between calls (not reliable)
var execTime = 2000; // time of execution of every onclick handler
var numberOfClicks = 3; // number of simulated clicks on document
var startDate = new Date;
var reg = /function|object/;
var debugLog = function (aReg) {
var fnBody;
if (aReg.test(typeof (Debug)) &&
aReg.test(typeof (Debug.write))) {
fnBody = 'Debug.write(aMsg);'; // IE
} else if (aReg.test(typeof (opera)) &&
aReg.test(typeof (opera.postError))) {
fnBody = 'opera.postError(aMsg);'; // Opera
} else if (aReg.test(typeof (console)) &&
aReg.test(typeof (console.log))) {
fnBody = 'console.log(aMsg);'; // FF, Safari etc.
} else {
return new Function;
};
return new Function('aMsg', fnBody);
}(reg);
var onClickListener = function () {
var s = new Date;
while ((new Date) - s < execTime);
debugLog('onclick handler: '
.concat((new Date) - startDate,
'ms since document has loaded.'));
if (numberOfCalls == 0) {
numberOfCalls++;
debugLog('setting interval');
var id = setInterval(function () {
if (numberOfCalls > callsLimit) {
return clearInterval(id);
};
debugLog('interval call number '
.concat(numberOfCalls++,
': ', (new Date) - startDate,
'ms since document has loaded.',
' (expected: ',
interval * (numberOfCalls - 1),
'ms).'));
}, interval);
};
};
(function (aEvt, aDoc, aClicks, aReg) {
var func;
if (!aReg.test(typeof (setInterval))) {
return false;
};
if (aReg.test(typeof (aDoc.addEventListener)) &&
aReg.test(typeof (aDoc.createEvent)) &&
aReg.test(typeof (aDoc.dispatchEvent))) {
var evt = aDoc.createEvent('MouseEvents');
if (aReg.test(evt.initMouseEvent)) {
func = function () {
evt.initMouseEvent(aEvt, true, true, window,
0, 0, 0, 0, 0, false, false,
false, false, 0, null);
aDoc.dispatchEvent(evt);
};
aDoc.addEventListener(aEvt, onClickListener, false);
};
} else if (aReg.test(typeof (aDoc.attachEvent)) &&
aReg.test(typeof (aDoc.fireEvent))) {
func = function () {
aDoc.fireEvent(aEvt);
};
aDoc.attachEvent(aEvt = 'on' + aEvt, onClickListener);
};
if (func) {
debugLog('The script has started, '
.concat(aClicks,
' clicks on the document is expected.',
' (each of them should take ',
execTime, 'ms).'));
while (aClicks-- > 0) {
func();
};
};
}('click', document, numberOfClicks, reg));
};
The script has started, 3 clicks on the document is expected. (each of them should take 2000ms).
onclick handler: 2039ms since document has loaded.
setting interval
onclick handler: 4043ms since document has loaded.
onclick handler: 6045ms since document has loaded.
interval call number 1: 6274ms since document has loaded. (expected: 1000ms).
interval call number 2: 7277ms since document has loaded. (expected: 2000ms).
interval call number 3: 8282ms since document has loaded. (expected: 3000ms).
interval call number 4: 9279ms since document has loaded. (expected: 4000ms).
interval call number 5: 10283ms since document has loaded. (expected: 5000ms).
Как работают таймеры в JavaScript