Warning in messages of Switch

Post Reply
User avatar
JimmyHartington
Advanced member
Posts: 267
Joined: Tue Mar 22, 2011 7:38 am

Warning in messages of Switch

Post by JimmyHartington »

I have begun to make more and more scripts with Node.JS.

And often I get this error in the messages of Switch.

Code: Select all

The script execution has ended while an async function or callback in the script might not have finished yet. Please check the script code for unresolved promises or missing await statements.
What is the best way to troubleshoot it?

In this case from the code below.

Code: Select all

// Create PDF using puppeteer (https://pptr.dev) from HTML-file as input
// Jimmy Hartington, Skabertrang, 2024-02-09

import * as fs from "fs";
import * as tmp from "tmp";
import puppeteer from "puppeteer";

async function jobArrived(s: Switch, flowElement: FlowElement, job: Job) {
  // puppeteer
  async function generatePDFfromHTML(document: string, outputPath: string) {
    const browser = await puppeteer.launch({
      args: [
        "--disable-web-security",
        "--disable-features=SameSiteByDefaultCookies,CookiesWithoutSameSiteMustBeSecure",
      ],
    });
    const page = await browser.newPage();
    await page.setUserAgent(
      "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36"
    );
    await page.setContent(document);
    await page.evaluateHandle("document.fonts.ready");
    await page.pdf({ path: outputPath, format: "A4" });
    await browser.close();
  }

  // Usage
  let jobName: string = (await job.getName(false)) as string;
  let jobPath: string = (await job.get(AccessLevel.ReadOnly)) as string;
  let htmlContent = await fs.readFileSync(jobPath, "utf-8");
  const tmpFile: string = await tmp.fileSync({
    prefix: "newfile",
    postfix: ".pdf",
  }).name;

  // puppeteer
  await generatePDFfromHTML(htmlContent, tmpFile)
    .then(() => job.log(LogLevel.Info, "PDF created"))
    .catch((err) => job.log(LogLevel.Error, "Error in creating pdf: " + err));

  let newJob = await job.createChild(tmpFile);
  await newJob.sendToSingle(jobName + ".pdf");

  // delete tmp files
  await fs.unlinkSync(tmpFile);

  // send original to null
  await job.sendToNull();
}

freddyp
Advanced member
Posts: 1000
Joined: Thu Feb 09, 2012 3:53 pm

Re: Warning in messages of Switch

Post by freddyp »

The best way to troubleshoot this is to start a debugging session. As you step through the code you should see what triggers the error. In this case it is pretty easy: you have 2 job.log statements that do not have an await.

I would like to make two side remarks. Everybody has their own coding style so the following is not criticism, but only suggestions that in my opinion increase readability. But again, you may find it to be the contrary.

You define the generatePDFfromHTML function inside the jobArrived function. I would put it at the end. Functions inside functions very quickly blur the overview.

I never use this coding pattern:

Code: Select all

await generatePDFfromHTML(htmlContent, tmpFile)
    .then(() => job.log(LogLevel.Info, "PDF created"))
    .catch((err) => job.log(LogLevel.Error, "Error in creating pdf: " + err));
    
let newJob = await job.createChild(tmpFile);
I use this one:

Code: Select all

try {
    await generatePDFfromHTML(htmlContent, tmpFile);
    job.log(LogLevel.Info, "PDF created"); //it is easier to see the await is missing here
} catch (error) {
    job.log(LogLevel.Error, "Error in creating pdf: " + err)); //same thing
}

let newJob = await job.createChild(tmpFile);
Now it also becomes clearer that your code will continue with createChild in case of an error and that will fail and the temporary file will not get cleaned up. Final version:

Code: Select all

const tmpFile: string = tmp.fileSync({ //putting await everywhere is also not a solution :)
    prefix: "newfile",
    postfix: ".pdf",
  }); //note that I removed .name so I keep the tmp object

try {
    await generatePDFfromHTML(htmlContent, tmpFile.name); //and I have to use .name here then
    await job.log(LogLevel.Info, "PDF created");
} catch (error) {
    job.fail(LogLevel.Error, "Error in creating pdf: " + err)); //job.fail perhaps strangely enough doesn't require await
    tmpFile.removeCallback(); //and now I use the object to remove the temporary file in the correct way
    return;
}

let newJob = await job.createChild(tmpFile);
User avatar
JimmyHartington
Advanced member
Posts: 267
Joined: Tue Mar 22, 2011 7:38 am

Re: Warning in messages of Switch

Post by JimmyHartington »

Thanks for your suggestions in regards to the code.
I do not take it as criticism. I have no formal education in coding, so this is a case of finding a way to convert HTML to PDF and combining the example from the documentation with code from some of my other scripts.

I will try to implement your suggestions.

In regards to debugging, is it possible to run the debug in Visual Studio Code on my mac, when Switch is running in my Windows server?
freddyp
Advanced member
Posts: 1000
Joined: Thu Feb 09, 2012 3:53 pm

Re: Warning in messages of Switch

Post by freddyp »

In regards to debugging, is it possible to run the debug in Visual Studio Code on my mac, when Switch is running in my Windows server?
Remote debugging in VSC is possible (https://learn.microsoft.com/en-us/visua ... ew=vs-2022) but I have never tried it. You will have to do stuff on the Windows server anyhow: stop the flow, activate debugging, activating the flow again and submit a job, modify the code, try again and so. Is it not a lot easier then to do the debugging on the Windows system?
Post Reply