# core.performMenuCommand({ commandId }) executed only after all other batchPlays

**URL:** <https://forums.creativeclouddeveloper.com/t/core-performmenucommand-commandid-executed-only-after-all-other-batchplays/3081>\
**Category:** UXP Plugin API\
**Tags:** bug, javascript\
**Created:** [June 10, 2021, 11:30pm UTC](https://forums.creativeclouddeveloper.com/t/core-performmenucommand-commandid-executed-only-after-all-other-batchplays/3081 "2021-06-10T23:30:56Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Karmalakas](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.creativeclouddeveloper.com/karmalakas/32/1048_2.png) [@Karmalakas](https://forums.creativeclouddeveloper.com/u/Karmalakas)\
**Post date:** [June 10, 2021, 11:30pm UTC](https://forums.creativeclouddeveloper.com/t/core-performmenucommand-commandid-executed-only-after-all-other-batchplays/3081/1 "2021-06-10T23:30:56Z")

</div>

I have a plugin which depends on selected layers. I also have another plugin, which, after performing some actions, selects specific layers. What I want, is for the second plugin to select layers only after I `performMenuCommand()` of the first plugin. All batchPlays here are synchronous.

```auto
// 2nd plugin actions
batchPlay(actions);
batchPlay([SAVE SELECTED LAYERS ACTIONS]);

batchPlay([SELECT LAYER FOR 1ST PLUGIN ACTION]);
core.performMenuCommand({ [1ST PLUGIN MENU COMMAND ID] });

// If I leave the line bellow, performMenuCommand() always fails 
// because it's executed only after all batchPlays bellow are done
// But if I comment this line out, menu command is run as expected,
// but then it wouldn't re-select the layers I need for the second plugin (obviously)
batchPlay([RE-SELECT PREVIOUSLY SAVED LAYERS ACTIONS]);

batchPlay([OTHER FINISHING ACTIONS WITHOUT CHANGING THE SELECTION]);

```

I see `performMenuCommand()` is async. Any way to make it synchronous too? Can’t find any docs (again) ☹

P. S. Sorry for this `[SYNTAX]`, it wouldn’t let me post because of `tooLongWords`

---

<div class="post-metadata">

**Author:** ![simonhenke](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.creativeclouddeveloper.com/simonhenke/32/957_2.png) [@simonhenke](https://forums.creativeclouddeveloper.com/u/simonhenke)\
**Post date:** [June 10, 2021, 11:49pm UTC](https://forums.creativeclouddeveloper.com/t/core-performmenucommand-commandid-executed-only-after-all-other-batchplays/3081/2 "2021-06-10T23:49:23Z")

</div>

Did you try to `await` it or wrap subsequent code in a `.then`-block?  
According to the prerelease types the function returns a `Promise<boolean>`.

---

<div class="post-metadata">

**Author:** ![Karmalakas](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.creativeclouddeveloper.com/karmalakas/32/1048_2.png) [@Karmalakas](https://forums.creativeclouddeveloper.com/u/Karmalakas)\
**Post date:** [June 11, 2021, 5:56am UTC](https://forums.creativeclouddeveloper.com/t/core-performmenucommand-commandid-executed-only-after-all-other-batchplays/3081/3 "2021-06-11T05:56:08Z")

</div>

I’m still very confused about all this `async/await` stuff 😕  
If I add `await`, then I have to add `async` to my whole function and it becomes asynchronous, doesn’t it? Also can’t get it to work with `then()` ☹

```auto
function doStuff() {
    async function executeCommand(commandId) {
        return await core.performMenuCommand({commandId});
    }

    executeCommand(-110).then(
        batchPlay([RE-SELECT PREVIOUSLY SAVED LAYERS ACTIONS]);
    );
}

```

But elsewhere I also have:

```auto
doStuff();
batchPlay([OTHER FINISHING ACTIONS WITHOUT CHANGING THE SELECTION]);

```

And `executeCommand()` promise is pending until everything is done. And for some reason when `executeCommand()` is finally done, layers are already re-selected. Looks like `then()` is performed before async is done 🤯

---

<div class="post-metadata">

**Author:** ![simonhenke](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.creativeclouddeveloper.com/simonhenke/32/957_2.png) [@simonhenke](https://forums.creativeclouddeveloper.com/u/simonhenke)\
**Post date:** [June 11, 2021, 9:38am UTC](https://forums.creativeclouddeveloper.com/t/core-performmenucommand-commandid-executed-only-after-all-other-batchplays/3081/4 "2021-06-11T09:38:28Z")

</div>

> [@Karmalakas](#):
>
> If I add `await` , then I have to add `async` to my whole function and it becomes asynchronous, doesn’t it?

Correct 👍 Also, if you’re returning a promise, it’s not even necessary to add the `await` keyword - if you think about it, what do you want to wait for in the scope of this function? return is always the last executed line, so there’s nothing after it. Btw, if you add async to your function, everything you return will already be a promise, which can also tidy up the code. I can really recommend typescript + tslint, it makes things so much easier and literally shows you all those little details:

 ![image](https://us1.discourse-cdn.com/flex015/uploads/xdplugins/original/2X/3/3566353e0d7986e795ce0960150882de984b1ec6.png)  
Here, the inferred return type is `Promise<number>` although I just return a number (because of `async`)

 ![image](https://us1.discourse-cdn.com/flex015/uploads/xdplugins/original/2X/e/e248eedcab54f4c611f5561c7c9c6cdb967d3da4.png)  
Tslint shows that you can remove `await` in return statements

![image](https://us1.discourse-cdn.com/flex015/uploads/xdplugins/original/2X/0/01bd6cd486c630ba3e62b1df87d12ffb4f082b95.png)

 ![image](https://us1.discourse-cdn.com/flex015/uploads/xdplugins/original/2X/f/f227b1e2f3a8e5e853727e54ba340500f05565c7.png)

* * *

In regards to your example: I’m still not sure what’s the exact order you want the code to run in. Do you want it to be like that:

1. performMenuCommand (start)
2. Other finishing actions
3. Reselect, once performMenuCommand is finished

?

---

<div class="post-metadata">

**Author:** ![Karmalakas](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.creativeclouddeveloper.com/karmalakas/32/1048_2.png) [@Karmalakas](https://forums.creativeclouddeveloper.com/u/Karmalakas)\
**Post date:** [June 11, 2021, 10:02am UTC](https://forums.creativeclouddeveloper.com/t/core-performmenucommand-commandid-executed-only-after-all-other-batchplays/3081/5 "2021-06-11T10:02:48Z")

</div>

> [@simonhenke](#):
>
> 1. performMenuCommand (start)
> 2. Other finishing actions
> 3. Reselect, once performMenuCommand is finished

Basically yes, but would prefer re-select before other finishing actions

---

<div class="post-metadata">

**Author:** ![simonhenke](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.creativeclouddeveloper.com/simonhenke/32/957_2.png) [@simonhenke](https://forums.creativeclouddeveloper.com/u/simonhenke)\
**Post date:** [June 11, 2021, 10:19am UTC](https://forums.creativeclouddeveloper.com/t/core-performmenucommand-commandid-executed-only-after-all-other-batchplays/3081/6 "2021-06-11T10:19:03Z")

</div>

```auto
async function executeCommand(commandId) {
    return core.performMenuCommand({commandId});
}

async function doStuff() {
    await executeCommand(-110)     
    batchPlay([RE-SELECT PREVIOUSLY SAVED LAYERS ACTIONS]);
}

await doStuff();
batchPlay([OTHER FINISHING ACTIONS WITHOUT CHANGING THE SELECTION]);

```

Maybe like this?

Also, in my code I always wrote `commandID`, but if `commandId` works fine for you this doesn’t seem to be case sensitive.

---

<div class="post-metadata">

**Author:** ![Karmalakas](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.creativeclouddeveloper.com/karmalakas/32/1048_2.png) [@Karmalakas](https://forums.creativeclouddeveloper.com/u/Karmalakas)\
**Post date:** [June 11, 2021, 10:25am UTC](https://forums.creativeclouddeveloper.com/t/core-performmenucommand-commandid-executed-only-after-all-other-batchplays/3081/7 "2021-06-11T10:25:21Z")

</div>

But again… If I add `await doStuff()`, then I have to add `async` all the way to the top function and that makes whole `myPluginCommand` asynchronous, doesn’t it? Wouldn’t it become something like this?

```auto
entrypoints.setup({
    commands: {
        myPluginCommand: async () => await myPluginCommand()
    }
});

```

---

<div class="post-metadata">

**Author:** ![simonhenke](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.creativeclouddeveloper.com/simonhenke/32/957_2.png) [@simonhenke](https://forums.creativeclouddeveloper.com/u/simonhenke)\
**Post date:** [June 11, 2021, 10:38am UTC](https://forums.creativeclouddeveloper.com/t/core-performmenucommand-commandid-executed-only-after-all-other-batchplays/3081/8 "2021-06-11T10:38:41Z")

</div>

Yes, but is that a problem? I’m not sure if the commands object expects any specific function type but I kinda doubt it. And if it does, you could still just call your async function in a synchronous `main()` function or similar.

Alternatively, you could also do it with then, which doesn’t require the parent function to be async if I remember correctly:

```auto
doStuff().then(() => {
    batchPlay([OTHER FINISHING ACTIONS WITHOUT CHANGING THE SELECTION]);
})

```

---

<div class="post-metadata">

**Author:** ![Karmalakas](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.creativeclouddeveloper.com/karmalakas/32/1048_2.png) [@Karmalakas](https://forums.creativeclouddeveloper.com/u/Karmalakas)\
**Post date:** [June 11, 2021, 10:47am UTC](https://forums.creativeclouddeveloper.com/t/core-performmenucommand-commandid-executed-only-after-all-other-batchplays/3081/9 "2021-06-11T10:47:58Z")

</div>

> [@simonhenke](#):
>
> `then(() => {})`

Ah… It’s a callback. I think that’s what I was missing. Will check again after work 🙂 Thanks

---

<div class="post-metadata">

**Author:** ![simonhenke](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.creativeclouddeveloper.com/simonhenke/32/957_2.png) [@simonhenke](https://forums.creativeclouddeveloper.com/u/simonhenke)\
**Post date:** [June 11, 2021, 11:15am UTC](https://forums.creativeclouddeveloper.com/t/core-performmenucommand-commandid-executed-only-after-all-other-batchplays/3081/10 "2021-06-11T11:15:34Z")

</div>

I also overlooked that in your code example, easy to miss. Good luck!

---

<div class="post-metadata">

**Author:** ![Karmalakas](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.creativeclouddeveloper.com/karmalakas/32/1048_2.png) [@Karmalakas](https://forums.creativeclouddeveloper.com/u/Karmalakas)\
**Post date:** [June 11, 2021, 4:35pm UTC](https://forums.creativeclouddeveloper.com/t/core-performmenucommand-commandid-executed-only-after-all-other-batchplays/3081/11 "2021-06-11T16:35:53Z")

</div>

Spent a couple of hours now, but can’t make it work ☹ At some point I had it working, but for some reason I got something like

> Can’t call `then()` on undefined

But now can’t even reproduce that 😢

I now even tried passing the callback all the way up to `core.performMenuCommand({commandId}).then(callback)`, but still `performMenuCommand()` is executed only after `callback` is done. WTH?

* * *

OK, here’s the full flow… I have batchPlay synchronous

```javascript
entrypoints.setup({
    commands: {
        mainCommand: () => mainCommand()
    }
});

const mainCommand = function () {
    let result = batchPlay(
        [lots, of, actions],
        historyState
    );

    batchPlay([actions, with, IDs, from, result]);

    runOtherPluginMenu(result[0].layerID);
};

const runOtherPluginMenu = function (id) {
    const allSelectedLayerIds = getSelectedLayersIDs();

    batchPlay([selectLayerWith_id]);

    const cb = () => {
        batchPlay([...reSelect_allSelectedLayerIds]);
    };

    const menuPath = ['menu', 'titles', 'path'];

    /// Here core.performMenuCommand() never gets executed ...
    // const menuItem = getMenuItemByPath(menuPath);
    // core.performMenuCommand(menuItem.command).then(cb);

    // ... But here it gets executed
    // except that core.performMenuCommand() is run only after layers are re-selected 
    // by running a callback in .then() in executeCommand() function
    runMenuCommand(menuPath, cb);
};

function runMenuCommand(path, callback = null) {
    const menuItem = getMenuItemByPath(menuPath);

    if (menuItem && typeof menuItem.command != 'undefined') {
        executeCommand(menuItem.command, callback);

        return;
    }

    if (typeof callback == 'function') {
        callback();
    }
}

function executeCommand(commandId, callback = null) {
    core.performMenuCommand({commandId}).then(callback);
}

```

---

<div class="post-metadata">

**Author:** ![Karmalakas](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.creativeclouddeveloper.com/karmalakas/32/1048_2.png) [@Karmalakas](https://forums.creativeclouddeveloper.com/u/Karmalakas)\
**Post date:** [June 12, 2021, 9:04am UTC](https://forums.creativeclouddeveloper.com/t/core-performmenucommand-commandid-executed-only-after-all-other-batchplays/3081/13 "2021-06-12T09:04:38Z")

</div>

Refactored two functions to this:

```auto
function runMenuCommand(path, callback = null) {
    const menuItem = getMenuItemByPath(menuPath);

    if (menuItem && typeof menuItem.command != 'undefined') {
        executeCommand(menuItem.command, callback);
    } else if (typeof callback == 'function') {
        callback();
    }
}

function executeCommand(commandId, callback = null) {
    let p = core.performMenuCommand({commandId});

    p.then(callback);
}

```

If I break on `p.then(callback)`, I see `p` is still `Pending` and only after it executes the callback, the menu item is triggered 😕 Might it be a bug?
