Это потому, что у вас напряженный цикл, который, по-видимому занимает больше времени, чем ваш таймер:
cnt = 10**9
--cnt while cnt > 0
Javascript в node.js однопоточны и события. Он может делать только одно за раз, и он завершит текущую работу, прежде чем он сможет обслуживать событие, отправленное setTimeout()
. Таким образом, если ваш цикл занятости (или любой другой длинный фрагмент кода Javascript) занимает больше времени, чем вы установили для своего таймера, таймер не сможет работать до тех пор, пока этот другой код Javascript не будет выполнен. «single threaded» означает, что Javascript в node.js выполняет только одно за раз, и он ждет, пока одна вещь вернет управление обратно в систему, прежде чем он сможет обслуживать следующее событие, ожидающее запуска.
Итак, вот последовательность событий в коде:
- Он называет
setTimeout()
запланировать обратный вызов таймера для 100мса теперь.
- Затем вы зайдете в свою занятую петлю.
- Пока он находится в цикле занятости, таймер
setTimeout()
срабатывает внутри реализации JS и вставляет событие в очередь событий Javascript. Это событие не может работать в данный момент, потому что интерпретатор JS все еще работает с циклом занятости.
- Затем, в конце концов, он завершает цикл занятости и возвращает управление обратно в систему.
- Когда это будет сделано, интерпретатор JS затем проверяет очередь событий, чтобы узнать, нуждаются ли в обслуживании любые другие события. Он находит событие таймера, и поэтому он обрабатывает это и вызывается callback
setTimeout()
.
- Этот обратный вызов разрешает обещание, которое вызывает обработчик
.then()
для вызова.
Примечание. Из-за однонаправленной и управляемой событиями Javascript таймеры в Javascript не могут быть вызваны именно тогда, когда вы их планируете. Они будут выполняться как можно ближе к ним, но если другой код работает в то время, когда они запускаются, или если у них много элементов в очереди событий впереди вас, этот код должен завершиться до того, как обратный вызов таймера фактически начнет выполняться.
Итак, если мы хотим знать, когда обещание фактически разрешено, КАК?
Обещание разрешается, когда выполняется цикл занятости. Это не разрешено точно в точке 100 мс (потому что ваш цикл занятости, по-видимому, занимает больше времени, чем 100 мс для запуска). Если вы хотите точно знать, когда обещание было разрешено, вы просто заходите в режим обратного вызова setTimeout()
, где вы звоните resolve()
. Это точно скажет вам, когда обещание было разрешено, хотя оно будет почти таким же, как и сейчас. Причиной вашей задержки является цикл занятости.
За ваши комментарии, кажется, что вы хотите как-то измерить точно, когда resolve()
на самом деле называется в Promise, но вы говорите, что вы не можете изменить код в getData()
. Вы не можете сделать это напрямую. Как вы уже знаете, вы можете измерить, когда вызывается обработчик .then()
, который, вероятно, будет не более чем через пару мс после вызова resolve()
.
Вы можете заменить инфраструктуру обещаний своей собственной реализацией, а затем вы можете обработать обратный вызов resolve()
напрямую, но замена или привязка реализации обещания, вероятно, влияет на сроки вещей даже больше, чем просто измерение из обработчика .then()
.
Итак, мне кажется, что вы только что сдерживали проблему. Вы хотите измерить, когда что-то внутри какого-либо кода происходит, но вы не допускаете каких-либо инструментов внутри этого кода. Это просто оставляет вас с двумя вариантами:
- Замените реализацию обещаний, чтобы вы могли непосредственно измерить прибор
resolve()
.
- Измерение при срабатывании
.then()
.
Первый вариант, вероятно, имеет проблему неопределенности в гейзенберге, поскольку вы, вероятно, повлияли на сроки больше, чем следует, если вы замените или примените реализацию обещания.
Второй вариант измеряет событие, которое происходит чуть позже фактического .resolve()
. Выберите, какой из них наиболее близок к тому, что вы на самом деле хотите.
Почему вы хотите знать это время? – Bergi
Фактическое! == предсказано. Без сюрпризов. –
@ Bergi причина, я делаю некоторые профилирования через протоколирование, мне нужно знать, когда HTTP-запрос фактически отвечает, без влияния другого кода. – luochen1990