Skip to content
EliteChart

Lazy-load history

Backfill bars on pan — only fetch what the user actually scrolls to.

EliteChart calls getBars once on mount, then again whenever the user pans into uncached territory. Your datafeed decides what "uncached" means — the chart hands you the requested [from, to] window; you return only those bars.

Quick example

code
import type { Bar, Datafeed, GetBarsRequest } from '@elitechart/elitechart';
import { asPrice, asTimestampMs, asVolume } from '@elitechart/elitechart';

const cache = new Map<string, ReadonlyArray<Bar>>();

export const lazyDatafeed: Datafeed = {
  async getBars(req: GetBarsRequest): Promise<ReadonlyArray<Bar>> {
    const key = `${req.symbol}|${req.resolution}|${req.from}|${req.to}`;
    const cached = cache.get(key);
    if (cached !== undefined) return cached;
    const r = await fetch(`/api/bars?symbol=${req.symbol}&from=${req.from}&to=${req.to}&tf=${req.resolution}`);
    const json = (await r.json()) as ReadonlyArray<{ t: number; o: number; h: number; l: number; c: number; v: number }>;
    const bars = json.map((b) => ({
      time: asTimestampMs(b.t), open: asPrice(b.o), high: asPrice(b.h),
      low: asPrice(b.l), close: asPrice(b.c), volume: asVolume(b.v),
    }));
    cache.set(key, bars);
    return bars;
  },
  subscribe() { return () => {}; },
};

How it works

The chart maintains a per-symbol bar buffer in memory. When the user pans left past the buffer's earliest bar, the chart calls getBars with from = earliest - viewport, to = earliest. Same on the right edge.

Your datafeed is responsible for caching, deduplicating, and returning data quickly — the chart is throttled to one refetch per ~120ms during pan, so you have a reasonable budget.

Variations

Pre-warm a wide history window on mount

code
import { useEffect } from 'react';
import { useChartHandle } from '@elitechart/elitechart';

function PreWarm() {
  const handle = useChartHandle();
  useEffect(() => {
    if (handle === null) return;
    handle.preloadHistory({ from: Date.now() - 365 * 86400_000, to: Date.now() });
  }, [handle]);
  return null;
}

Throttle hard

code
import { throttle } from 'lodash-es';
const throttledFetch = throttle(fetchBars, 1000);

API

MethodFromNotes
Datafeed.getBars(req)host appviewport-driven refetch
handle.preloadHistory(window)@elitechart/elitechartone-shot pre-warm