Как обернуть вызовы асинхронных функций в функцию синхронизации в Node.js или Javascript?

Предположим, вы поддерживаете библиотеку, которая предоставляет функциюgetData, Ваши пользователи называют это, чтобы получить фактические данные:
var output = getData();
Под капотом данные сохраняются в файл, чтобы вы реализовалиgetData используя Node.js встроенныйfs.readFileSync, Это очевидно, какgetData а такжеfs.readFileSync являются функциями синхронизации. Однажды вам сказали переключить базовый источник данных на репозиторий, такой как MongoDB, доступ к которому возможен только асинхронно. Вам также сказали, чтобы не разозлить ваших пользователей,getData API нельзя изменить, чтобы он возвращал просто обещание или требовал параметр обратного вызова. Как вы соответствуете обоим требованиям?

Асинхронная функция, использующая обратный вызов / обещание, является основой JavasSript и Node.js. Любое нетривиальное приложение JS, вероятно, пронизано этим стилем кодирования. Но эта практика может легко привести к так называемой пирамиде обратного вызова судьбы. Еще хуже, если какой-либо код в любом вызывающем объекте в цепочке вызовов зависит от результата асинхронной функции, этот код также должен быть включен в функцию обратного вызова, накладывая ограничение на стиль кодирования для вызывающего. Время от времени я нахожу необходимость инкапсулировать асинхронную функцию (часто предоставляемую в сторонней библиотеке) в функцию синхронизации, чтобы избежать масштабного глобального ре-факторинга. Поиск решения по этому вопросу обычно заканчивалсяВолокна узла или пакеты 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.