документации не указывается такое поведение
NodeJS-х documentation for setInterval
характерно не указывает практически ничего о своем поведении, кроме того, что он будет повторять эту задачу.
результаты, которые я думал, что будет в том, что каждая итерация будет выполняться через 1 секунду независимо от того, сколько времени выполнения функции интервала принимает
Если вы имеете в виду, вы могли бы перекрывающихся казни, вы не можете в NodeJS; он запускает ваш код в одном потоке.
Если вы хотите, чтобы каждая итерация выполнялась через секунду после последнего завершения, это не так, как традиционно работает setInterval
. У setInterval
традиционно было по крайней мере два разных поведения в зависимости от того, какую реализацию вы использовали: планирование следующей итерации в начале текущего текущего или планирование его на конец текущего. И это только в браузерах. Это с been standardized for browsers, но NodeJS не является браузером и не требуется работать одинаково. (И на самом деле это не по-другому: в браузерах требуется вернуть номер setInterval
, а в NodeJS он возвращает объект.) Помните, что таймеры не являются особенностью JavaScript, они являются функцией среды хоста.
Вместо этого, чтобы запустить его второй (примерно) после его завершения, используйте setTimeout
в конце функции, чтобы запланировать следующую, чтобы запустить секунду позже.
Re правки:
почему в NodeJS, когда у меня есть setInterval() установлен на 1 секунду, а выполнение функции занимает 3 секунды, поэтому следующий исполнение 7 секунд вместо 4 секунд или даже 3 секунды. для меня это действительно странное поведение. что приемлемое поведение?
Да. Это странно и удивительно (на мой взгляд), но NodeJS определяет свое поведение для setInterval
, поэтому приемлемо. В моих экспериментах (ниже), по-видимому, измеряется, как долго выполнялось предыдущее выполнение вашей функции, затем добавьте, чтобы длина таймера была равна lastExecutionLength + desiredInterval
, прежде чем она снова заработает. Это явно не соответствует спецификации для браузеров, но опять же, NodeJS не является браузером.
Вот мой тестовый скрипт:
let counter = 0;
let timeAtEndOfLastExecution = 0;
let timer = null;
function log(msg) {
console.log(Date.now() + ": " + msg);
}
function tick() {
let start = Date.now();
if (timeAtEndOfLastExecution) {
log("tick (" + (Date.now() - timeAtEndOfLastExecution) + "ms)");
} else {
log("tick");
}
if (++counter == 10) {
clearInterval(timer);
} else {
let wait = 200 + (Math.floor(8 * Math.random()) * 100);
log("waiting " + wait + "ms");
let stopWaiting = Date.now() + wait;
while (Date.now() < stopWaiting) {
// busy wait
}
log("exiting callback after " + (Date.now() - start) + "ms");
timeAtEndOfLastExecution = Date.now();
}
}
timer = setInterval(tick, 200);
И пробег образец (с узлом v6.2.2):
1468396730618: tick
1468396730619: waiting 400ms
1468396731020: exiting callback after 416ms
1468396731637: tick (617ms)
1468396731637: waiting 500ms
1468396732137: exiting callback after 500ms
1468396732837: tick (700ms)
1468396732837: waiting 900ms
1468396733737: exiting callback after 900ms
1468396734837: tick (1100ms)
1468396734837: waiting 300ms
1468396735137: exiting callback after 300ms
1468396735637: tick (500ms)
1468396735637: waiting 700ms
1468396736337: exiting callback after 700ms
1468396737237: tick (900ms)
1468396737237: waiting 800ms
1468396738037: exiting callback after 800ms
1468396739036: tick (999ms)
1468396739036: waiting 900ms
1468396739936: exiting callback after 900ms
1468396741036: tick (1100ms)
1468396741036: waiting 700ms
1468396741736: exiting callback after 700ms
1468396742636: tick (900ms)
1468396742636: waiting 200ms
1468396742836: exiting callback after 200ms
1468396743236: tick (400ms)
Как мы видим, он постоянно ждет длину предыдущей итерации плюс интервал, который я дал:
- Первый обратный вызов занял в общей сложности 416 мс; следующий начался 617 мс после его возвращения
- Второй обратный вызов занял 500 мс; следующий заработал 700 мс после его возвращения
- Третий обратный вызов 900 мс; следующий запустил 1100 м после его возвращения
@Andreas: NodeJS однопоточный; JavaScript - это * не *. –