Предположим, что вы поддерживаете библиотеку, которая предоставляет функцию getData
. Ваши пользователи назовут его для получения фактических данных: var output = getData();
Под капотом данные сохраняются в файле, поэтому вы внедрили getData
с помощью Node.js встроенного fs.readFileSync
. Очевидно, что функции getData
и fs.readFileSync
являются функциями синхронизации. Однажды вам сказали переключить базовый источник данных на репо, например MongoDB, к которому можно получить доступ только асинхронно. Вам также сказали не беспокоить своих пользователей, getData
API не может быть изменен, чтобы вернуть просто обещание или потребовать параметр обратного вызова. Как вы отвечаете обоим требованиям?
Асинхронная функция с использованием обратного вызова/обещания - это ДНК JavasSript и Node.js. Любое нетривиальное приложение JS, вероятно, пронизано этим стилем кодирования. Но эта практика может легко привести к так называемой обратной пирамиде гибели. Хуже того, если какой-либо код в любом вызывающем абоненте в цепочке вызовов зависит от результата функции async, этот код также должен быть включен в функцию обратного вызова, накладывая ограничение стиля кодирования на вызывающего. Время от времени я нахожу необходимость инкапсулировать функцию асинхронизации (часто предоставляемую в сторонней библиотеке) в функцию синхронизации, чтобы избежать массового глобального повторного факторинга. Поиск решения по этому вопросу обычно заканчивался Node Fibers или пакетами npm, полученными из него. Но Fibers просто не могут решить проблему, с которой я столкнулся. Даже пример, представленный автором Фибера, иллюстрирует недостаток:
...
Fiber(function() {
console.log('wait... ' + new Date);
sleep(1000);
console.log('ok... ' + new Date);
}).run();
console.log('back in main');
Фактический выход:
wait... Fri Jan 21 2011 22:42:04 GMT+0900 (JST)
back in main
ok... Fri Jan 21 2011 22:42:05 GMT+0900 (JST)
Если функция Fiber действительно переключает асинхронную функцию в режим синхронизации, выход должен быть:
wait... Fri Jan 21 2011 22:42:04 GMT+0900 (JST)
ok... Fri Jan 21 2011 22:42:05 GMT+0900 (JST)
back in main
Я создал еще один простой пример в JSFiddle и ищет код для получения ожидаемого результата. Я приму решение, которое работает только в Node.js, поэтому вы можете требовать любой пакет npm, несмотря на то, что не работаете в JSFiddle.