FR: Make Component.load() asyncable

Component.load() and Component.onload() are defined as void methods. However Plugin.onload is defined as Promise<void> | void

Reverse engineering Component.load() I see that it’s written assuming component can return Promise<void>, it uses Promise.all() internally.

We can define our components like

class MyComponent extends Component {
  public override async onload(): Promise<void> {
  }
}

but @typescript-eslint/no-misused-promises eslint rule will complain

I propose to change the Component API to

class Component {
  public load(): Promise<void> | void;
  public onload(): Promise<void> | void;
  // ...
}

Then plugin writers can choose to override them with void or Promise<void> depending on their needs.

Current Component.load() implementation loads children in parallel and swallows all possible errors

Roughly speaking it’s implemented like

const childPromises: (Promise<void> | undefined)[] = [];
for (const child of this._children) {
  childPromises.push(child.load() as Promise<void> | undefined);
}

Promise.all(childPromises).then();

Here we see that synchronous child.load() are executed sequentially, but asynchronous ones are executed in parallel, which might potentially cause some race conditions.

If you implement this FR, it will allow you to stop swallowing possible child promise rejections and consider loading async children sequentially.