Home > Software design >  Waiting till inner promises are done
Waiting till inner promises are done

Time:12-07

I want to wait that two or more Promises will be blocked, as long there results will be for me avaible.

Therefore I am using the Promise.allSettled method. This is working if the two Promises are flat. But if one of that Promises consists of inner Promises then it won't work.

 Promise.allSettled([
  report?.getActivePage(), //return a Promise object
  exportVisualData("9df20366a984c945beb5")
 ])
  .then((results) => {
    results.forEach((result, index) => {
      if (result.status === "rejected") {
        const rejectedResult: PromiseRejectedResult =
          result as PromiseRejectedResult;
        console.log(rejectedResult);
      } else if (result.status === "fulfilled") {
        if (index === 0) {
          const fulfilledResult: PromiseFulfilledResult<Page | undefined> =
            result as PromiseFulfilledResult<Page | undefined>;
          console.log(fulfilledResult);
          fulfilledResult.value?.setActive();
        } else {
          const fulfilledResult: PromiseFulfilledResult<void | IExportDataResult> =
            result as PromiseFulfilledResult<void | IExportDataResult>;
          console.log(fulfilledResult);
        }
      }
   });

function exportVisualData(id: string): Promise<void | IExportDataResult> {
return report!.getPages().then((pages) => {
  pages.forEach((page) => {
    page.getVisuals().then((visualDescriptors) =>
      visualDescriptors.forEach((visualDescriptor) => {
        if (visualDescriptor.name === id) {
          if (!page.isActive) {
            page.setActive().then((__) => {
              return visualDescriptor?.exportData(
                ExportDataType.Summarized
              );
            });
          } else {
            return visualDescriptor?.exportData(ExportDataType.Summarized);
          }
        }
      })
    );
  });
});

Promise.allSettled hasn't have a result in the second due to the inner promises, how could I can get this to work.

{status: 'fulfilled', value: Page} {status: 'fulfilled', value: undefined}

CodePudding user response:

Here's a rewritten exportVisualData() function that collects whatever results meet your visualDescriptor.name test into an array and makes that array the resolved value of the promise that exportVisualData() returns.

I didn't know if visualDescriptor?.exportData(ExportDataType.Summarized) returns a promise or not. In case it does, I put an await in front of it. If it just returns a value directly, you can remove that await.

Also, I don't know TypeScript so you will have to add type info to this code:

async function exportVisualData(id: string): Promise < void | IExportDataResult > {
    const results = [];
    const pages = await report!.getPages();
    for (let page of pages) {
        let visualDescriptors = await page.getVisuals();
        for (let visualDescriptor of visualDescriptors) {
            if (visualDescriptor.name === id) {
                if (!page.isActive) {
                    await page.setActive();
                }
                results.push(await visualDescriptor?.exportData(ExportDataType.Summarized));
            }
        }
    }
    return results;
}

Note, this does not run all these asynchronous operations in parallel, so there is no need to use Promise.allSettled() on the result. It just returns a single promise that resolves to an array of values.

If you want to catch errors and keep processing in this function, you can try/catch in each loop and continue in the catch.

If you wanted to run everything in parallel, that is more difficult to code here because of your if (visualDescriptor.name === id) that wants to skip some items so you don't know how many results you are waiting for until you're far into the results.

  • Related