ngxtension / ngxtension-platform

Utilities for Angular
https://ngxtension.netlify.app/
MIT License
592 stars 87 forks source link

Feature Suggestion: waitForSignal #476

Open ShacharHarshuv opened 2 months ago

ShacharHarshuv commented 2 months ago

Hey! First of all - amazing library! I'm just looking over at these utilities and they look really strong! Some are things I had implemented myself (but your implementation is better) and some are things I haven't even thought that I need!

I had an idea that might fit your library (if it doesn't - no problem).

function waitForSignal<T, U extends T>(
    value: Signal<T>,
    filter: (value: T) => value is U,
  ): Promise<U>;

An example use-case would be if you have a signal with a loading state, but you want to wait for a loaded value:

const loadedValue = await waitForSignal(data, data => data.isLoaded).then(data => data.value);

Here's an example implementation of this:

export function injectWaitForSignal() {
  const injector = inject(Injector);

  return function waitForSignal<T, U extends T>(
    value: Signal<T>,
    filter: (value: T) => value is U,
  ) {
    return new Promise<U>((resolve) => {
      const effectRef = effect(
        () => {
          const v = value();
          if (filter(v)) {
            resolve(v);
            effectRef.destroy();
          }
        },
        {
          injector,
        },
      );
    });
  };
}

I wrapped it in an injection function, because a) I need an injection context, and b) it's unlikely that the consumer will have that injection context when they want to call it, if there are multiple awaits. I feel like that simplifies things for the consumer as they can call it in the beginning and then use the function as many time as they want.