Forum Academy Marketplace Showcase Pricing Features

Plugin Action (context.async) will not execute more than once

I have a plugin action …

As you can see the function returns asynchronously and does a console log. Unfortunately the issue is that I perform this action one time and it works, but when I try to run it again it the code runs (the console.log(‘run’) is executed … ) but the context.async does not.

I’m not sure why that’s the case. What am I missing here? Any help would be appreciated :slight_smile:

1 Like

I have this exact same problem while using context.async in plugin element actions.
I managed to run context.async several times on client-side actions only, with the exact same code.
I believe this issue deserves a bug report.

1 Like

Really? Damn … So I need to use client-side actions I guess. :frowning:

There are some mismatched design patterns in your use of promises and asynchronous functions:

  1. Unless you need to extract a value from a promise or asynchronous function, or want to catch the promise rejection of a server side function in the server logs there is no need to wrap your asynchronous code in acontext.async.
  2. You are passing the (undefined) result of calling console.log to the error handling part of the callback. This is problematic and will result in unpredictable behaviour.
  3. Ditto for your promise result, you are passing the (undefined) result of console.log to a eventually a return statement. Again more unpredictable behaviour.
  4. Pick either return Promise or async function for your design pattern, not both. I personally prefer the older promise chaining as it forces me, as a developer, to think explicitly about asynchronous dependencies and orders of operation.

I would refactor your code to stick to one design pattern. For example using promise chaining:

function(instance, properties, context) {

    // Start (writes first)
    console.log("Start");

    // Process (writes third)
    instance.data.whiteboard.board.get()
    .then((s) => { console.log(s); })
    .catch((r) => { console.log(r); });

     // End (writes second)
     console.log("End")
}

Note: there are browser and Node.js dependent idiosyncrasies when parsing anonymous functions. Some are more tolerant of partial syntax than others. I always use fully “curly brace” anonymous syntax to guard against parser errors.

Server-side pattern using context.async to mimic await behaviour:

const mypromise = makeapromise();
const myresolved = context.async(
    (callback) => {
        mypromise
        .then((result) => { callback(null, result); })
        .catch((reason) => { callback(reason); });
    }
);

Note: You can chain as many thens and Promise.alls or Promise.anys together outside of context.async before finally extracting a value with context.async

2 Likes

Still the same.
Only one execution for plugin’s element action possible.
So it seems impossible to async set elements states???