I
I
Itvanya2016-03-15 00:53:26
JavaScript
Itvanya, 2016-03-15 00:53:26

How to asynchronously parse data from a folder into JSON using node.js?

Hello. The task is this: there is a small site that stores a folder on the server in which the folders of music albums are located, in which the musical compositions themselves are located and also one photo (.jpg) is required - a cover for the album. You need to parse all this data in JSON to the same directory asynchronously. My script works without problems, but at a certain point I lose data and can't get the data out of the object so I can JSON encode it later. The server is completely working according to the Restful api scheme. I'm with asynchronous programming on "you" so far, but in express I have not met this, because everything is out of the box.

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 // Кавер для альбома
                };
            });
        }
    });
});

Next, you need to convert the cache object to JSON and write the corresponding file. The problem is that in the synchronous version, everything is clear: the file is parsed, crammed into a variable, then we write it where necessary. Here you can explicitly get the cache variable only through setTimeout after the explicit completion of the asynchronous loop. Does the JSON data need to be written right inside the deepest loop, checking to see if the data has been added to the JSON file before?
Sorry for such a massive question! Thanks :)

Answer the question

In order to leave comments, you need to log in

1 answer(s)
N
netW0rm, 2016-03-15
@Itvanya

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()
    })
});

something like this

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question