0

I need to pass a function creating a Promise and have an availability to start it again. The Promise is one time state machine, so there is no restart functionality. This answer suggests to wrap a Promise in a function. But my attempts either do not work or do not compile.

This is an interface:

export interface LoaderContext {
    action: Promise<any>;
}

export class LoaderMachine {
    private readonly initialContext: LoaderContext;

    constructor(action: Promise<any>) {
        this.initialContext = { action, retries: 0 };
    }

Here I use the service, the method can be called multiple times:

async fetchData(context: LoaderContext) {
    try {
        await context.action;
    } catch (err) {
        console.error(`Failed with ${err}`);
    }
}

A sample Promise I use for testing

function executeRequest() {
  return new Promise<void>((resolve, reject) => {
    setTimeout(() => {
      if (new Date().getSeconds() % 5 > 1) {
        reject('Bad luck');
      } else {
        resolve();
      }
    }, 3000)
  });
}

And how I call it:

this.loaderService = new LoaderMachine(executeRequest()).service;

How to adapt a Promise in a function so I can call it multiple time? Or did I misunderstood that answer? I need to pass such functions:

this.setupConfig()
this.getUserCredentials.bind(this)
Leos Literak
  • 8,805
  • 19
  • 81
  • 156
  • If context.action is a promise and never changes, then once it has settled (to value or error) it is permanently settled. Your `fetchData()` is only indirectly creating a promise (from another promise). Unless you can fix that you are stuck. You have to originate the context.action promise again. If it were a function (context.action()) that created a new Promise each time you would be golden. Then you can repeatedly wait on a new promise in try/catch each time in your async `fetchData()`. Its return value will be a Promise of the eventual result (even if it took 3 actions to get there) – cefn Sep 09 '22 at 09:39
  • I wonder if passing a function as a reference would do the trick. I can call it multiple times and get new Promise each time. – Leos Literak Sep 09 '22 at 11:52

1 Answers1

0

Ok, passing a function is the way to go:

export interface LoaderContext {
    action: () => Promise<void>;
}

await context.action();

this.loaderService = new LoaderMachine(executeRequest).service;
Leos Literak
  • 8,805
  • 19
  • 81
  • 156