0

I have a problem with my html-pdf document creation. The problem is that often the code runs to fast to complete the process of pdf-docutment creation. The Processes consists out of building an HTML-String by replacing placeholders in an Html file. Below you see the code what happens afterwards.

                            Object.keys(setter).forEach(function(element, key, _array) {
                              var regex = new RegExp(element, "g");

                              data = data.replace(regex, setter[element])
                            })

                            var result = data;

                            fs.writeFile(mergeFileRes, result, 'utf8', function (err) {
                                if(err) { 
                                    console.log(err); 
                                    return;
                                } else {

                                    let html2 = fs.readFileSync(mergeFileRes, 'utf8');
                                    let options = { 
                                        format: 'a4' , 
                                        "directory" : "/tmp",
                                    };                            

                                    if(html2){
                                        pdf.create(html2, options).toStream(function(err, stream2){
                                            if(err)  console.log(err);
                                            stream2.pipe(res);

                                            stream2.on('end', function () {
                                                try{
                                                    fs.unlink(mergeFileRes)
                                                    console.log(3090, "deleted file");
                                                }
                                                catch (err){
                                                    console.log(3090, "Did not delete file");
                                                }
                                            });
                                        });
                                    } else {

                                    }
                                }
                            });

My problem is that in many cases the html2 variable is not yet created before the pdf.create process starts. This is probably because the readFileSync takes too long to finish.

I was wondering, how can I fix this. How can I make the pdf.create wait for the readFileSync to finish and the html2 variable to be filled.

RutgerBrns
  • 85
  • 2
  • 10
  • 1
    readFileSync is a synchronous call, untill reading is not complete it won't go ahead. console read data after reading. – AZ_ Feb 01 '19 at 11:33
  • *This is probably because the readFileSync takes too long to finish* - no, it doesn't, the function is sync, as the name suggest. The problem is elsewhere, – Estus Flask Feb 01 '19 at 11:34
  • So the object.keys/data.replace function might be taking too long? I think you might be right. But, but how can I force the code to wait for this process to finish then? – RutgerBrns Feb 01 '19 at 11:47

1 Answers1

1

You can use fs.readFile to read the file asynchronously and html2 will be available within the callback function.

Object.keys(setter).forEach(function(element, key, _array) {
    var regex = new RegExp(element, "g");

    data = data.replace(regex, setter[element])
})

var result = data;

fs.writeFile(mergeFileRes, result, 'utf8', function (err) {
    if(err) { 
        console.log(err); 
        return;
    } else {

        fs.readFile(mergeFileRes, 'utf8', function(err, html2){
            if (err) throw err;

            let options = { 
                format: 'a4' , 
                "directory" : "/tmp",
            };                            

            pdf.create(html2, options).toStream(function(err, stream2){
                if(err)  console.log(err);
                stream2.pipe(res);

                stream2.on('end', function () {
                    try{
                        fs.unlink(mergeFileRes)
                        console.log(3090, "deleted file");
                    }
                    catch (err){
                        console.log(3090, "Did not delete file");
                    }
                });
            });
        });
    }
});
Dan Nagle
  • 4,384
  • 1
  • 16
  • 28
  • Thanks for the answer. The code works, but still getting this error now and then: GET /api/bill/pdf/5c52eba76369863df45f5712 200 2043.263 ms - - assert.js:42 throw new errors.AssertionError({ ^ AssertionError [ERR_ASSERTION]: html-pdf: Can't create a pdf without an html string. How can there still be no html string if I am telling the code to wait for it? – RutgerBrns Feb 01 '19 at 11:44
  • 1
    You're working on the assumption that `Object.keys(setter).forEach()` has completed the data updates before the remaining code is executed. But the only thing you can guarantee is that the callback is called for each element. You are not waiting for the callbacks to complete before continuing. You might want to consider using `Promises` in series and when the final promise completes execute the code that should follow. – Dan Nagle Feb 01 '19 at 12:41