2015-08-13 2 views
2
"use strict" 

const 
    fs = require('fs'), 
    stream = fs.createReadStream("file.txt"), 
    timeout = 0; 

stream.on('data', function() { 
    console.log("File Read"); 
}); 

setTimeout(function(){ 
    console.log("setTimeout : " + timeout); 
}, timeout); 

Я учусь Node.js/JavaScript и мне было интересно, почему эта программа возвращенияОтветный порядок очереди в маленьком Node.js примере

setTimeout : 0 
File Read 

, а не наоборот.

Исправить меня, если я ошибаюсь, но в javascript очередь обратного вызова является fifo, сначала укладывая stream и сначала?

Я думаю, что из-за неблокирующем природы nodejs, как обратный вызов выполняются в «параллельной» и setTimeout отделки первого и возврата (например, тайм-аут 1000 мс переключит результаты.)

ответ

4

Исправьте меня, если я ошибаюсь, но в javascript очередь обратного вызова - fifo, сначала укладывает поток и выходите первым?

Не совсем. Асинхронные обратные вызовы обрабатываются FIFO в порядке, в котором они завершают свои операции, а не в порядке их запуска. Таким образом, время, которое требуется выполнить операции, очень важно при определении того, когда обратный вызов будет назначен. Короткие операции могут завершаться до завершения операций, даже если они были запущены позже.

Требуется время, чтобы открыть файл и начать его читать, а setTimeout() не требует времени, чтобы это произошло первым. Когда у вас есть независимые асинхронные операции, вы почти никогда не можете «знать», в каком порядке они будут происходить, потому что это зависит от внутреннего времени различных функций.

Операция readStream запускается до запуска таймера, но таймер заканчивается до того, как операция readStream получает свои первые данные только из-за объема работы, требуемой для внутренних операций async.

Я думаю, что из-за неблокирующем природы nodejs, как обратного вызова выполняются в «параллельно» и SetTimeout заканчивает первый и возврата (например, тайм-аут 1000 мс переключит результаты.)

Да, это правильно.


Подумайте об этом. У вас есть два мощных мегафона и действительно хороший микрофон. Вы настроили две цели, чтобы указать на мегафон и прослушать возвращаемое эхо. Одна цель, т.е. очень близкая, и одна цель находится очень далеко. Сначала вы запускаете мегафон на очень отдаленную цель, а затем сразу же взрываете мегафон у ближайшей цели. Не удивительно, что вы получаете эхо от ближней цели, даже если вы отправили его взрыв после первого, просто потому, что эхо от дальней цели занимает намного больше времени, чтобы пройти все его дополнительное расстояние и вернуться к вам. То же самое можно сказать о вашем readStream. Несмотря на то, что вы начали его сначала, он занимает намного больше времени, чем setTimeout(fn, 0), поэтому сначала заканчивается setTimeout() и, таким образом, вызывает его обратный вызов.


Если выбор время важно для вас, то вам следует использовать такие инструменты, как обещания конкретно последовательность ваших операций асинхронных или ждать, пока все необходимые результаты не будут готовы.Хорошая конструкция не должна «предполагать», что одна асинхронная операция будет завершена перед другой, если только ваш код не гарантирует, что путем последовательности операций.

0

Удивительно, что я сделал видеоурок, объясняющий эту концепцию 2 дня назад, и вы спросили об этом. Do watch this 9 min video to get a good understanding of this. Вот объяснение. Существует концепция Eventloop в Nodejs и в JS в целом. Что делает Eventloop, так это то, что он держит часы над запущенным кодом и в стеке. Как вы сказали, что когда-либо вставляется в стек из кода, это FIFO. Однако, если есть какие-либо асинхронные или обратные методы или действия, которые должны быть выполнены, Eventloop переходит в действие, чтобы позаботиться об этом. Какая eventloop по сути делает 8s, что у нее есть очередь, где она поддерживает эти методы обратного вызова. Когда стек свободен, этот фрагмент кода из очереди помещается в стек и выполняется.

0

Это происходит исключительно из-за неблокирующей функции узла js. Операция чтения файла - это объект ввода-вывода, поэтому он будет перенесен в очередь событий, и функция setTimeOut будет выполнена немедленно. Как только чтение файла будет выполнено, используя его обратный вызов, он присоединится к основному потоку управления. Следовательно, setTimeOut будет выполнен первым, а затем Файл будет прочитан. Просто.

Смежные вопросы