Unresolved Promises

Post Reply
DtM
Member
Posts: 26
Joined: Tue Aug 04, 2015 3:02 pm

Unresolved Promises

Post by DtM »

Hello,

I'm trying to write a script which should sort files in a folder in a particular way.

Code: Select all

import fs from "fs";
import path from "path";
import tmp from 'tmp-promise';

function naturalSort(arr: String[]){
    return arr.map(v => {
        let processedName = [];
        let str = v;
        for(let i = 0; i < str.length; i++) {
            let isNum = Number.isInteger(Number(str[i]));
            let j;
            for(j = i + 1; j < str.length; j++) {
                if(Number.isInteger(Number(str[j])) != isNum) {
                    break;
                }
            }
            processedName.push(isNum ? Number(str.slice(i, j)) : str.slice(i, j));
            i = j - 1;
        }
        return processedName;
    }).sort((a, b ) => {
        let len = Math.min(a.length, b.length);
        for(let i = 0; i < len; i++) {
            if(a[i] != b[i]) {
                let isNumA = Number.isInteger(a[i]);
                let isNumB = Number.isInteger(b[i]);
                if(isNumA && isNumB) {
                    return Number(a[i]) - Number(b[i]);
                } else if(isNumA) {
                    return -1;
                } else if(isNumB) {
                    return 1;
                } else {
                    return a[i] < b[i] ? -1 : 1 ;
                }
            }
        }
        // in case of one string being a prefix of the other
        return a.length - b.length;
    }).map(v => v.join(''));
}

async function getFiles(dir: string) {
    const items = await fs.promises.readdir(dir);
    const files = [];
    for (const item of items) {
        const itemPath = path.join(dir, item);
        const itemStat = await fs.promises.stat(itemPath);
        if (itemStat.isDirectory()) {
            return false;
        } else {
            files.push(itemPath);
        }
    }
    return files;
}

async function jobArrived(s: Switch, flowElement: FlowElement, job: Job) {
    try {
        const jobPath = await job.get(AccessLevel.ReadOnly);
        if (job.isFile()) {
            job.fail('You can only sort the contents of a job folder. Nothing can be done to single files.');
            return;
        } else {
            let files = await getFiles(jobPath);
            
            if (!files) {
                job.fail('Nested folders are unsupported, please supply a folder of loose files only.');
                return;
            } else {
                files = naturalSort(files);
            }

            // Calculate how many zeros we need to pad the filenames with - this is the length of the number of items rather than the number of items itself.
            const padding = String(files.length).length;

            // Set a counter to add to the new filenames.
            let counter = 1;

            tmp.withDir(async o => {
                await Promise.all(
                    // @ts-ignore
                    files.map(async (file: string) => {
                        const newPath = path.join(o.path, `${String(counter).padStart(padding, '0')}_${path.basename(file)}`);
                        counter++;
                        await fs.promises.copyFile(file, newPath);
                    })
                );

                // Once we have copied all of the files, convert the new folder to a job and pass it to the flow.
                const newJobFolder = await job.createChild(o.path);
                await newJobFolder.sendToSingle();

                // Discard the original files.
                await job.log(LogLevel.Info, "'%1' was sent to null.", [job.getName()]);
                // await job.sendToNull();
            }, { unsafeCleanup: true, prefix: 'SORT' });
        }
    } catch (e) {
        job.fail("Failed to process the job '%1': %2", [job.getName(), (e as Error).message]);
    }
}
When I attempt to run the script however I get the following mesage:
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.
I try to run the debugger to find out where the issue is but my breakpoints are completely ignored and the only way to stop Switch to stop processing my test folder is to force quit Switch all together.

Can anyone offer any advice as to why this isn't working?

Thanks
mkayyyy
Member
Posts: 75
Joined: Mon Nov 21, 2016 6:31 pm
Location: UK

Re: Unresolved Promises

Post by mkayyyy »

It looks like it could be because you're not awaiting the tmp.withDir call? Not tested this but looks like it should be:

Code: Select all

await tmp.withDir(async o => {
	await Promise.all(
		// @ts-ignore
		files.map(async (file: string) => {
			const newPath = path.join(o.path, `${String(counter).padStart(padding, '0')}_${path.basename(file)}`);
			counter++;
			await fs.promises.copyFile(file, newPath);
		})
	);

	// Once we have copied all of the files, convert the new folder to a job and pass it to the flow.
	const newJobFolder = await job.createChild(o.path);
	await newJobFolder.sendToSingle();

	// Discard the original files.
	await job.log(LogLevel.Info, "'%1' was sent to null.", [job.getName()]);
	// await job.sendToNull();
}, { unsafeCleanup: true, prefix: 'SORT' });
DtM
Member
Posts: 26
Joined: Tue Aug 04, 2015 3:02 pm

Re: Unresolved Promises

Post by DtM »

Hi Matthew,

Thank you for the quick response - that was indeed the issue.

Can't believe I missed that - definite case of snow blindness!

Thanks again,

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

Re: Unresolved Promises

Post by freddyp »

Apart from the unresolved promise issue, what is missing in "Sort files in job" to accomplish what you need?
DtM
Member
Posts: 26
Joined: Tue Aug 04, 2015 3:02 pm

Re: Unresolved Promises

Post by DtM »

freddyp wrote: Mon May 15, 2023 2:19 pm Apart from the unresolved promise issue, what is missing in "Sort files in job" to accomplish what you need?
Hi Freddy,

I need the files to be returned using a "natural" sort.

I.E if I have 10 files named File 1.pdf through File 10.pdf, I want them to be listed alphabetically and numerically.

I tried using the built in sort and the one available on the app store as part of the folder tools and both returned File 1, File 10, File 2 etc.
DtM
Member
Posts: 26
Joined: Tue Aug 04, 2015 3:02 pm

Re: Unresolved Promises

Post by DtM »

Also it's worth noting that the file names won't always fit this example pattern - they could be anything.
Post Reply