Understanding synchronicity with Photoshop batchPlay

Hi!

I’m working on a Photoshop UXP plugin (API Version 2) and am trying to write a function that writes all the image layers out as PNGs to a particular folder.

The following code attempts to loop through the active document layers and export them out with batchPlay. The console output suggests that the operations are happening in the correct order, but only the bottom layer (the last element of activeDocument.layers) actually gets exported to the folder. It seems like the batchPlay commands aren’t actually being called when I think they are, perhaps I’m not understanding how to execute synchronous batchPlay commands correctly? I saw the same behaviour when not using async functions too

async function testExport() {
    try {
        const { app } = require("photoshop");

        await require("photoshop").core.executeAsModal(
            async () => {
                for (let layer of app.activeDocument.layers) {
                    // Select layer.
                    const selectAction = {
                        _obj: "select",
                        _target: [
                            {
                                _ref: "layer",
                                _id: layer.id,
                            },
                        ],
                        makeVisible: false,
                        layerID: [layer.id],
                        _isCommand: true,
                    };
                    console.log("selecting", layer.id);
                    await require("photoshop").action.batchPlay(
                        [selectAction],
                        {
                            synchronousExecution: true,
                            modalBehavior: "execute",
                        }
                    );
                    console.log("selected", layer.id);

                    // Export selected layer.
                    const exportAction = {
                        _obj: "exportSelectionAsFileTypePressed",
                        _target: {
                            _ref: "layer",
                            _id: layer.id,
                        },
                        fileType: "png",
                        quality: 32,
                        metadata: 0,
                        destFolder: destFolder,
                        sRGB: true,
                        openWindow: false,
                        _options: { dialogOptions: "dontDisplay" },
                    };
                    console.log("exporting", layer.id);
                    await require("photoshop").action.batchPlay(
                        [exportAction],
                        {
                            synchronousExecution: true,
                            modalBehavior: "execute",
                        }
                    );
                    console.log("exported", layer.id);
                }
            },
            { commandName: "Export Layers" }
        );
    } catch (err) {
        console.error(err);
    }
}                 

Any help would be very much appreciated!

Thanks,
Nik

What’s the return result from the batchPlay commands? You might be getting errors there (batchPlay doesn’t always throw on an error).

Hi @kerrishotts!

The batchPlay commands are returning an array of one empty object:

[
    {}
]

No errors are being reported to the console.

Thanks!
Nik

Also just to mention, when I remove the loop and just tell it to export the currently selected layer it works without issue! It’s only having issues once I put it into the loop.

I’m guessing there’s more in that object – a lot of objects have properties that can’t be enumerated when you log them out, so they look empty, but often are not.

Try logging this instead:

const result = await /*the rest of your command */
console.log(result.map(item => `${item._obj} ${item.message}`).join("\n"));

What do you get now?

2 Likes

When I try that I simply receive undefined undefined in the console for the export command.

I tried calling the export function on layers by ID manually in the function below:

async function testExport() {
    const { executeAsModal } = require("photoshop").core;

    let result1 = await executeAsModal(
        function () {return exportLayerByID(6);},
        { commandName: "Export layer 6" }
    );

    let result2 = await executeAsModal(
        function () {return exportLayerByID(14);},
        { commandName: "Export layer 14" }
    );

    let result3 = await executeAsModal(
        function () {return exportLayerByID(15);},
        { commandName: "Export layer 15" }
    );
}

Commenting out two of them allows me to export any of the layers without issue, but once I run all three of them in the function only two are exported… not sure what’s going on.