Javascript-форум (https://javascript.ru/forum/)
-   Node.JS (https://javascript.ru/forum/node-js-io-js/)
-   -   Непредсказуемая функция. (https://javascript.ru/forum/node-js-io-js/71259-nepredskazuemaya-funkciya.html)

Rora_ 05.11.2017 03:17

Непредсказуемая функция.
 
Всем добрый день. В процессе прочтения книги М.Каскиаро "Шаблоны проектирования Node.JS", описана следующая проблема, техническая сторона возникновения которой от меня ускользает, я опишу проблему тут, так как она описана в книге, прошу растолковать и так сказать помочь в понимании.

Есть функция результат выполнения которой не предсказуем:

const fs = require('fs');
const cache = {};
function inconsistentRead(filename, callback) {
	if (cache[filename]){
		callback(cache[filename]);
	}else{
		fs.readFile(filename,'utf-8',(err,data)=>{
			cache[filename]=data;
			callback(data);
		});
	}
}

function createFileReader(filename) {
	const listeners = [];
	inconsistentRead(filename,value=>{
		listeners.forEach(listener=>listener(value)); 
	});
	return {
		onDataReady: listener=>listeners.push(listener) // во 1 я первый раз увидел присвоение свойства таким элегантным образом, если можно, ссылку где об этом можно почитать. А во 2 что есть listener в данном случае?
	};
}

const reader1 = createFileReader('text.txt');
reader1.onDataReady(data=>{
	console.log('First call data:'+data);
	const reader2 = createFileReader('text.txt');
	reader2.onDataReady(data=>{
		console.log('Second call data:'+data)
	})
});

Выведет
First call data: Some data

И в 3 самое главное, автор пишет:
ВО время создания reder1 функция inconsistentRead() выполняется асинхронно, поскольку в кэше еще нет результата. Таким образом имеется возможность зарегистрировать обработчика, что и будет сделано в другой итерации цикла событий, до завершения операции чтения.
Затем в итерации цикла событий создастся reader2, когда файл уже находится в кэше. В этом случае внутренний вызов, inconsistentRead() ,будет выполнен синхронно. То есть он выполнит функцию обратного вызова немедленно, и соответственно все обработчики события reader2 также будут вызваны синхронно. Однако регистрация обработчиков выполняется после создания reader2, поэтому они никогда не будут вызваны.

Вот, этот итог меня ввел в ступор. Растолкуйте плз, о каких обработчиках идет речь. И почему вообще это так работает. Спасибо.

Alexandroppolus 05.11.2017 14:43

Речь, как я понимаю, про inconsistentRead.

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

Для наличия данных в кэше добавляем асинхронность искусственно:
if (cache[filename]){
    process.nextTick(callback, cache[filename]);
}

Alexandroppolus 05.11.2017 15:27

А вообще, данный пример правильнее через промисы делать. Тогда и заморочки с listeners не понадобятся, и асинхронность промис берет на себя.

Rora_ 07.11.2017 08:34

Да, спасибо я понял. Действительно, с промисами намного легче.


Часовой пояс GMT +3, время: 04:39.