-1

I am facing some confusion as to how my promises are working in my node.js web application.

  let arrayPics = [];
        let conv = ()=>{
            return new Promise((resolve,reject)=>{
                let check=converter.convert(req);
                if(check)
                    resolve('Conversion');
                else
                    reject();
            });
        };

        let enc = (message)=>{
            return new Promise((resolve,reject)=>{
               let check =  encode.encoder(arrayPics);
               if(check)
                   resolve(message + ' and Encoding to Base 64!');
                else
                    reject();
            });
        };

        conv().then((result)=>{
            return enc(result);
        }).then((result)=>{
            console.log('Finished '+result);
            console.log(arrayPics[4]);
            return res.redirect('/ViewDoc');
        });

So basically my first promise is running a script to convert pdf and tiff file documents to seperate png files in a temp folder. Then the second promise runs a script to convert the pngs to base 64 and store it in a dynamic array. When I consume the promises I get the output as something like this :

{ title: '' }
{ fieldname: 'upl',
  originalname: 'multipage_tiff_example.tif',
  encoding: '7bit',
  mimetype: 'image/tiff',
  destination: 'uploads/',
  filename: 'multipage_tiff_example.tif',
  path: 'uploads\\multipage_tiff_example.tif',
  size: 810405 }
Finished Conversion and Encoding to Base 64!
undefined
POST / 302 181.742 ms - 60
GET /ViewDoc 304 8.564 ms - -
Converted!

We can see that the console.log(arrayPics[4]) output is coming out as undefined. But when i run the same code while debugging my code I get the following output.

Debugger listening on [::]:54395
Server is listening on: 3000
GET / 304 35.525 ms - -
{ title: '' }
{ fieldname: 'upl',
  originalname: 'multipage_tiff_example.tif',
  encoding: '7bit',
  mimetype: 'image/tiff',
  destination: 'uploads/',
  filename: 'multipage_tiff_example.tif',
  path: 'uploads\\multipage_tiff_example.tif',
  size: 810405 }
Finished Conversion and Encoding to Base 64!
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAyAAAAJYCAIAAAAVFBUnAAAABGdBTUEAAL.......
Converted!

We can see that now we get an output for console.log(arrayPics[4]). This is the part where I am getting confused as to why my code is behaving like that. I have also posted my scripts that my promises are using for your reference:

DOCUMENT CONVERTER SCRIPT:

module.exports = {

    convert: function pdfConverter(req)
    {   let check = true;
        gm(req.file.path).write('Images/output.png', (err)=>
        {
            if(err)
            {
                console.log(err);
                reject(err);
                check = false;
            }

            else
            {
                console.log("Converted!");

            }

        });
        return check;
    }

};

BASE64 ENCODING

module.exports = {
    encoder: function base64_encoder(arrayPics)
            {
                let files = fs.readdirSync('Images/');
                for(let i in files)
                {
                    //console.log('C');
                    arrayPics.push(base64Img.base64Sync('Images/output-' + i + ".png"));
                }
                return true;
            }
};

I would be grateful if i can get some suggestions as to why this is happening and any changes that I can make to my code.

Vmal
  • 27
  • 9

1 Answers1

1

The problem is in your document converter script. You pass a callback function to the .write() method. In other words, it's asynchronous, but your convert() function returns synchronously. You return check right away, before it's potentially set to false in the callback.

What you need to do is to make the convert() function return a Promise that resolves or rejects in the callback that you pass to the .write() method.

Then in your application script, your conv() function declaration can be simplified to this: let conv = () => converter.convert(req);

Also, as it stands your encoder is NOT asynchronous, so there's no point in wrapping it in a Promise.
You can make it asynchronous though, for instance by using .readdir() instead of .readdirSync(). If you do, the same thing that I explained about your converter applies to your encoder.

Lennholm
  • 7,205
  • 1
  • 21
  • 30