neocotic / convert-svg

Node.js packages for converting SVG into other formats using headless Chromium
MIT License
198 stars 45 forks source link

Can you provide a Sync example? #35

Closed focussing closed 5 years ago

focussing commented 6 years ago

I need to convert a big directory tree and delete the SVG file after creating the JPG file

neocotic commented 6 years ago

@focussing The libraries only work asynchronously as they rely on interacting with a headless Chromium instance, which can only be done asynchronously. With async/await syntax you can write asynchronous code in a synchronous fashion. If you absolutely must do it synchronously, you may need to get inventive/hacky, like spawning a synchronous child process, however, this could have an impact on performance.

focussing commented 6 years ago

Yep, you are right. Sorry for bothering.

How about using existence of the generated SVG file? Would that be an option?

neocotic commented 6 years ago

Can you please clarify what you mean? Possibly with an example.

focussing commented 6 years ago

Basically I want to convert a directory structure consisting of 1100 SVG files to the same structure but then consisting of JPG files.

What I do right now is to walk through the structure generated by readdirp. The readdirp callback is fired when the structure is complete. Next I loop through the files list and convert SVG to JPEG. Now I do that with a timer.

When the conversion is complete I want to delete the SVN file.

Another option would be to walk through the file structure again, and delete the SVN files. Of course that can be done in a lot of different ways.

Code snippet :)

// https://github.com/thlorenz/readdirp
var readdirp = require('readdirp');

var settings = {
    root: outPath,
    entryType: 'files',
    fileFilter: '*.svg'
};

// In this example, this variable will store all the paths of the files and directories inside the providen path
var allFilePaths = [];

// Iterate recursively through a folder
readdirp(settings,
    // This callback is executed everytime a file or directory is found inside the providen path
    function(fileInfo) {

        // Store the fullPath of the file/directory in our custom array
        allFilePaths.push(
            fileInfo.fullPath
        );

    },

    // This callback is executed once
    function(err, res) {
        if (err) {
            throw err;
        }

        // An array with all the fileEntry objects of the folder
        // console.log(res);
        //console.log(allFilePaths);
        // ["c:/file.txt",""]

        let i = 0;
        // const stopAt = 10;
        const stopAt = allFilePaths.length;

        let timer = setInterval(function() {
            let progress = i / stopAt * 100;
            console.log(progress + '% ' + allFilePaths[i]);
            const outputFilePath = convertFile(allFilePaths[i], options);
            // console.log(outputFilePath);

            if (++i == stopAt) {
                clearInterval(timer);
                console.log('conversion done')
            }
        }, 250)

        // allFilePaths.forEach(function(f) {
        //     convertFile(f, options);
        // });
    }
);
neocotic commented 6 years ago

This appears to be out of scope for this library and involves more of an understanding on managing asynchronous flows within Node.js. I'm not sure that I understand your timer logic, but the following should do what you're asking for:

const { convertFile } = require('convert-svg-to-jpeg');
const fs = require('fs');
const glob = require('glob');
const util = require('util');

const findFiles = util.promisify(glob);
const removeFile = util.promisify(fs.unlink);

(async() => {
  const allFilePaths = await findFiles('*.svg', { absolute: true, cwd: outPath, nodir: true });

  for (const filePath of allFilePaths) {
    await convertFile(filePath, options);
    await removeFile(filePath);
  }
})();

All written like synchronous code with the benefit that it's fully asynchronous and non-blocking.

I'm not familiar with readdirp so I used glob for demonstration purposes.

This could even allow for parallel conversion and/or deletion if you wanted to, but that's even further out of the scope of this library. Lots of resources out there to help there though.

focussing commented 6 years ago

Yep you are right about out-of-scope. I just mentioned it related to checking whether the converted jpg is present and use that as a trigger.

But; thanks for your example code! I will test your solution and come back to that :) Have a great day!