Непредсказуемая функция.
Всем добрый день. В процессе прочтения книги М.Каскиаро "Шаблоны проектирования 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, поэтому они никогда не будут вызваны. Вот, этот итог меня ввел в ступор. Растолкуйте плз, о каких обработчиках идет речь. И почему вообще это так работает. Спасибо. |
Речь, как я понимаю, про inconsistentRead.
Если есть функция с колбеком, и этот колбек в некоторых случаях может вызваться только асинхронно (в данном примере - при отсутствии данных в кэше), то функция должна быть написана так, чтобы колбек всегда вызывался асинхронно. Для наличия данных в кэше добавляем асинхронность искусственно: if (cache[filename]){ process.nextTick(callback, cache[filename]); } |
А вообще, данный пример правильнее через промисы делать. Тогда и заморочки с listeners не понадобятся, и асинхронность промис берет на себя.
|
Да, спасибо я понял. Действительно, с промисами намного легче.
|
Часовой пояс GMT +3, время: 04:39. |