Задать вопрос
@Itvanya

Как асинхронно запарсить данные из папки в JSON, используя node.js?

Всем привет. Задача такая : есть небольшой сайт, который на сервере хранить папку, в которой расположены папки музыкальных альбомов, в которых расположены сами музыкальные композиции и также обязательно одна фотография(.jpg) - cover для альбома. Нужно запарсить все эти данные в JSON в эту же директорию асинхронно. Мой скрипт работает без проблем, но на определенном моменте я теряю данные и не могу вывести данные из объекта, чтобы потом кодировать их JSON. Сервер полностью работает по Restful api схеме. Я с асинхронным программированием на "вы" пока, а в express с таким не встречался, потому что все из коробки.
var cache = {};

fs.readdir(__dirname, function(err, data) { // Читаем текущую директорию
    if (err) throw err; // Обработали ошибку, если есть
    data.forEach(function(item) { // Для каждой папки в директории начинаем перебор
        if (isFolder(item)) { // Если это - папка, то продолжаем
            cache[item] = {}; // Наименование папки(муз.альбом) - объект, кот. будет хранить данные о нем

            fs.readdir(__dirname + `/${item}`, function(err, songList) { // Читаем внутренности папки(альбома)
                let songArray = [], // Найденные песни копим сюда
                    cover = null; // Контейнер для кавера для альбома
                if (err) throw err;
                songList.forEach(function(song) { // Для каждой песни в альбоме
                    if (isSong(song)) { // Если это - песня, а не фотография или еще чего, то добавляем в массив
                        songArray.push(song);
                    } else if (isPic(song)) { // Если фотография - присваиваем её переменной
                        cover = song;
                    }
                }); // Цикл перебора для текущей папки(альбома) закончен, запускается следующий
                cache[item] = { // Тут мы присваиваем данные объекту(item-название альбома)
                    songs: songArray, // Массив с песнями
                    cover: cover // Кавер для альбома
                };
            });
        }
    });
});


Далее нужно объект cache преобразовать в JSON и записать соответствующий файл. Проблема в том, что в синхронном варианте все понятно : файл пропарсился, забился в переменную далее мы его записываем куда нужно. Тут явным образом получить переменную cache можно только через setTimeout после явного завершения асинхронного цикла. Неужели данные в JSON нужно записывать прямо внутри самого глубокого цикла, делая проверку на то, добавлялись ли эти данные ранее в JSON-файл?

Извините за столь массивный вопрос! Спасибо :)
  • Вопрос задан
  • 569 просмотров
Подписаться 2 Оценить Комментировать
Решения вопроса 1
@netW0rm
var cache = {};
function writeJson() {
	fs.writeFile(JSON.stringify(cache), cb)
}
fs.readdir(__dirname, function(err, data) { // Читаем текущую директорию
    if (err) throw err; // Обработали ошибку, если есть
    var promises = []
    data.forEach(function(item) { // Для каждой папки в директории начинаем перебор
        promises.push(new Promise((resolve, reject) => {
          if (isFolder(item)) { // Если это - папка, то продолжаем
              cache[item] = {}; // Наименование папки(муз.альбом) - объект, кот. будет хранить данные о нем

              fs.readdir(__dirname + `/${item}`, function(err, songList) { // Читаем внутренности папки(альбома)
                  let songArray = [], // Найденные песни копим сюда
                      cover = null; // Контейнер для кавера для альбома
                  if (err) throw err;
                  songList.forEach(function(song) { // Для каждой песни в альбоме
                      if (isSong(song)) { // Если это - песня, а не фотография или еще чего, то добавляем в массив
                          songArray.push(song);
                      } else if (isPic(song)) { // Если фотография - присваиваем её переменной
                          cover = song;
                      }
                  }); // Цикл перебора для текущей папки(альбома) закончен, запускается следующий
                  cache[item] = { // Тут мы присваиваем данные объекту(item-название альбома)
                      songs: songArray, // Массив с песнями
                      cover: cover // Кавер для альбома
                  };
                  resolve()
              });
          }
          else {
          	resolve()
          }
        });
    });
    Promise.all(promises).then(() => {
    	writeJson()
    })
});

както так
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы