0
 let base64Data: string;
 let attachment: Attachment;  
 let blob: Blob;
 docList.forEach(([pdfDoc, title]) => {
            blob = pdfDoc.output('blob'); 
            var reader = new FileReader();
            reader.readAsDataURL(blob);
            reader.onloadend = function() {
              base64data = reader.result;
              attachment = new Attachment();
              attachment.setFilename(title);
              attachment.setContent(base64data);
              attachment.setType('application/pdf');
              attachments.push(attachment);
            }
         });

pdfDoc is a jsPDF; Attachment is my own class with fields as indicated.

If I run the above code in debug mode and add breakpoints, the attachments array is populated as I expected. Otherwise the array ends up blank. I know there is an issue with synchronizing the looping and the the FileReader. I found the following answer

Looping through files for FileReader, output always contains last value from loop

but I'm not sure how to apply it to my case. Any suggestions? Thanks in advance.

1 Answers1

0

I reckon the main problem is, that you kill your array attachment with each loop on the one hand and on the other hand you simply missed the plural s.

 let base64Data: string;
 let attachment: Attachment;  <<== plural s is missing
 let blob: Blob;

 docList.forEach(([pdfDoc, title]) => {
        blob = pdfDoc.output('blob'); 
        var reader = new FileReader();
        reader.readAsDataURL(blob);
        reader.onloadend = function() {
          base64data = reader.result;
          attachment = new Attachment(); <<== kills the array and overwrites it
          attachment.setFilename(title);
          attachment.setContent(base64data);
          attachment.setType('application/pdf');
          attachments.push(attachment); <<== never writes the value anywhere
        }
     });

So try it this way:

 let attachments: Attachment; // with plural s

 docList.forEach(([pdfDoc, title]) => {
        const blob = pdfDoc.output('blob'); 
        const reader = new FileReader();
        reader.readAsDataURL(blob);
        reader.onloadend = function() {
          const base64data = reader.result;
          const attachment = new Attachment(); // without plural s
          attachment.setFilename(title);
          attachment.setContent(base64data);
          attachment.setType('application/pdf');
          attachments.push(attachment); // writes to the intended array

          // how to know when the last item was added?
          if(attachments.length === docList.length) {
              showListContent();
          }
        }
     });

     function showListContent() {
         console.log(attachments);
     }

Avoid variables with unnecessarily broad scopes as often as you can. function scoped variables should always be your first choice, if applicable.

  • All good advice, but still incomplete. There is no way of knowing when `attachment` will be fully populated with this code. – Patrick Roberts Jul 29 '18 at 18:23
  • Point taken. Solved it. –  Jul 29 '18 at 18:30
  • @user3803175: Please, don't forget to mark this answer as solution if it solved your problem. Thanks in advance. Lynx –  Jul 29 '18 at 18:35