npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@ngbasics/polling

v13.0.5

Published

Dispatch actions like HTTP requests in recurring intervals

Downloads

1

Readme

Polling Module

The polling module provides a factory service, which allows you to create polling tasks declaratively.

Installation

npm i @ngbasics/polling

Usage

  1. Import the module
  2. Inject the factory service
  3. Create a polling handle
  4. Subscribe/Update handle

TL;DR

// register module
@NgModule({
  imports: [
    PollingModule.forChild({
      initialDelay: 0,
      pollingRate: 30_000,
    }),
  ],
})
export class MyModule {}

// use factory
@Component()
export class MyComponent {
  public polling = this.factory.create(() => this.http.get('https://my-domain/api/v1/data'));

  constructor(private factory: PollingFactoryService, private http: HttpClient) {}
}
<!-- subscribe to status$ to start polling -->
<div>{{ polling.status$ | async }}</div>
<button (click)="polling.update()">Update immediatly</button>

Exhaustive

First register the module with the forChild initializer.

@NgModule({
  imports: [PollingModule.forChild()],
})
export class MyModule {}

Then inject the factory service.

@Injectable()
export class MyService {
  constructor(private pollingFactory: PollingFactoryService) {}
}

The factory service can now be used to create polling handles. Provide an action as first argument.

Note: An Action is a factory function that returns an Observable.

const myAction = () => of('action was executed');

@Injectable()
export class MyService {
  public polling = this.pollingFactory.create(myAction);

  constructor(private pollingFactory: PollingFactoryService) {}
}

The handle exposes a status$ Observable and an update function.

  • Receive updates by subscribing to status$.
  • Trigger an immediate update by calling update().

Note: Don't forget to unsubscribe, when your caller is destroyed, or the polling will continue to run.

Note: Calling update() will not reset the polling interval.

@Component()
export class MyComponent {
  constructor(myService: MyService) {
    myService.polling.status$.subscribe(console.log);
    myService.polling.update();
  }
}

Configuration

The module allows configuration of the polling interval as well as the delay until the first execution.

Module scope

@NgModule({
  imports: [
    PollingModule.forChild({
      initialDelay: 0, // instantly start polling
      pollingRate: 30_000, // then execute every 30s
    }),
  ],
})
export class MyModule {}

Component scope

const pollingConfig: Partial<PollingConfig> = {
  initialDelay: 42,
};

@Component({
  providers: [
    {
      provide: PollingConfigToken,
      useValue: pollingConfig,
    },
    // don't forget to provide an instance of the service
    PollingFactoryService,
  ],
})
export class MyComponent {}

Factory scope

@Injectable()
export class MyService {
  public polling = this.pollingFactory.create(myAction, {
    pollintRate: 42,
  });

  constructor(private pollingFactory: PollingFactoryService) {}
}

Tips

Actions can be anything

You can schedule arbitrary actions with your factory function.

const fetchData = () => http.get('https://my-domain.com/api/v1/data');
const logSomething = () => of(console.log('scheduler will log this'));

pollingFactory.create(fetchData);
pollingFactory.create(logSomething);

Combine with POST/PUT

Update the status immediatly after modifying a resource.

const url = 'https://my-domain/api/v1/items';

const getItems = (http: HttpClient) => () => httpClient.get<Item[]>(url);

@Injectable()
export class MyService {
  public polling = this.pollingFactory.create(getItems(this.http));

  constructor(private pollingFactory: PollingFactoryService, private http: HttpClient) {}

  public createItem(item: Item): Observable<Item> {
    return concat(
      defer(() => this.http.post<void>(url, item)),
      defer(() => this.polling.update())
    );
  }
}

Terminate polling

Unsubscribe from status$ to cancel the polling.

Note: You can trigger immediate updates with handle.update() even after termination.

const url = 'https://my-domain/api/v1/items';

const getItems = (http: HttpClient) => () => httpClient.get<Item[]>(url);

@Injectable()
export class MyService {
  public polling = this.pollingFactory.create(getItems(this.http));

  constructor(private pollingFactory: PollingFactoryService, private http: HttpClient) {}

  public startPolling(destroy$: Observable<void>): void {
    this.polling.status$.pipe(takeUntil(destroy$)).subscribe();
  }
}

With the takeUntil() convenience method you can ensure that callers must provide a termination criterion before the polling can start.

const url = 'https://my-domain/api/v1/items';

const getItems = (http: HttpClient) => () => httpClient.get<Item[]>(url);

@Injectable()
export class MyService {
  private _polling = this.pollingFactory.create(getItems(this.http));

  constructor(private pollingFactory: PollingFactoryService, private http: HttpClient) {}

  public getHandle(destroy$: Observable<void>): PollingHandle<Item> {
    return this._polling.takeUntil(destroy$);
  }
}
// in your component
this.myService.getHandle(this.destroy$).status$.subscribe();

For a complete example check out the example-app in this repository.