Асинхронная запись файлов в цикле, как управлять потоками

#node.js #fs #node-canvas

#node.js #fs #узел-холст

Вопрос:

Я пытаюсь записать более 100 файлов png через node-canvas в цикле. Генерируется только 40 файлов, а затем процесс завершается.

Я попытался создать поток png с помощью createPNGStream () и передать результаты в поток записи, созданный fs.createWriteStream().

Функция записи:

 function writeFile(row, col) {
        // canvas code ...
        const stream = canvas.createPNGStream();
        let path = __dirname   '/imgs/heatmapRow'   row   "Col"   col   '.png';
        const out = fs.createWriteStream(path);
        stream.pipe(out);
        out.on('finish', () => console.log('The PNG file was created.'))
    }
  

Вызывающая функция:

 function generateImages(){
    var numRows = 20;
    var numCols = 5;
    for(let row = 0; row < numRows;   row) {
        for (let col = 0; col < numCols;   col) {
            writeFile(row, col);
        }
    }
}
  

Цикл запускается и завершается, и в конце я получаю кучу следующих строк одновременно:

Файл PNG был создан. Файл PNG был создан. Файл PNG был создан. Файл PNG был создан.

Я думаю, что в каждом цикле создается поток записи, который является асинхронным. Процесс завершается, потому что у меня может быть открыто только определенное количество потоков.

Как я могу записать все свои файлы и сделать это асинхронно, чтобы ускорить время обработки? (Я предпочитаю не записывать файлы синхронно) Нужно ли добавлять каждый файл для записи в очередь? Как мне определить ограничение на количество открытых мной потоков и как мне управлять ими?

Комментарии:

1. То есть в основном генерируется только 40/100 файлов?. Вы видите какую-либо ошибку?.

2. Это около 40 изображений. Один раз было 37, один раз было 43. У меня не было никаких ошибок.

Ответ №1:

Вы должны использовать Promises для выполнения ваших асинхронных вызовов. Я даю вам решение:

   function writeFile(row, col) {
    // canvas code ...
    const stream = canvas.createPNGStream();
    let path = __dirname   "/imgs/heatmapRow"   row   "Col"   col   ".png";

    return new Promise(resolve => {
      const out = fs.createWriteStream(path);
      stream.pipe(out);
      out.on("finish", () => {
        console.log("The PNG file was created.");
        resolve();
      });
    });
  }

  function generateImages() {
    var numRows = 20;
    var numCols = 5;
    var imagesToGenerate = [];
    for (let row = 0; row < numRows;   row) {
      for (let col = 0; col < numCols;   col) {
        imagesToGenerate.push(writeFile(row, col));
      }
    }

    Promise.all(imagesToGenerate).then(() => {
      console.log("All images generated");
    });
  }
  

Взгляните на Promise.все документы если вы не совсем понимаете, как это работает