Search code examples
typescriptpromiseasync-awaites6-promise

Performance issue with Promises, setTimeout, async/await on Edge


Is there anything inherently wrong with the following mixed use of asnyc/await, promise, and setInterval? It's working as desired, but the performance is terrible on Edge. My test case runs in about 3.5 sec in Chrome, but takes over 2 min in Edge. Note that this is a method from a TypeScript class.

public async exportPdf(sourceGraph: IGraph, filters: EntityFilter) {
        if (sourceGraph) {
            ...snip....
            for (let verticalPageIndex = 0; verticalPageIndex < pagesHighWithMargins; verticalPageIndex++) {
                for (let horizontalPageIndex = 0; horizontalPageIndex < pagesWideWithMargins; horizontalPageIndex++) {
                    // run with setTimeout so we can process other events between pages and prevent locking up the browser
                    await new Promise(resolve => setTimeout(resolve, 0)).then(async () => {
                        ...snip...
                        const svgElement = await exporter.exportSvgAsync(exportComponent) as SVGElement;
                         ....snip - expensive code to convert SVG to PDF page...
                    });
                }
            }

            return jsPdf.output('datauristring');
        } else {
            return new Promise((_, reject) => {
                reject(new Error('graph argument is null'));
            });
        }
    }

Obviously I'm a newbie with JS and TS, but I've been around long enough to know that mixing 3 different techniques for managing async operations is probably wrong. :-)


Solution

  • I'm closing out this question because I've isolated my primary issue -- performance when using the Edge browser -- to a library I'm using to convert SVG to PDF and not my use of promises, setTimeout, or async/await, but any further insight on the additional findings below is appreciated!

    @Bergi's suggestions are much appreciated, but I'm probably still be missing something. If I don't include the lines after await new Promise(...) inside the then(), my loops complete before I've generated the content of my PDF pages, which causes the next steps -- exporting the complete PDF content as a string and saving to disk -- to fail. I need this loop to complete synchronously so I get all the PDF content in the correct order. The only reason I'm using new Promise(resolve => setTimeout(resolve, 0)) is to slightly improve the browser's responsiveness during the loop, which is working pretty much as shown in the original post.

    I did removed the async from the then's callback and switched to a synchronous version of the exportSvg function and it's working well. Simply awaiting the call to exporter.exportSvgAsync without enclosing it in a await new Promise(resolve => setTimeout(resolve, 0)).then(...) did not allow the browser to be responsive at all inside the loop though.