200.Land

async-iterator.ts

The JavaScript code defines an async iterable class CustumIterable parameterized over two types, which facilitates iteration over a sequence of async fetched items defined by a starting index and next index computation function. A showDogs function demonstrates its usage, iterating over dog objects asynchronously fetched by ID until undefined is returned, signaling the end of the iterable.

interface ICustomIterableParams<T, IndexType> {
  index: IndexType;
  nextIndex: (index: IndexType, item: T) => IndexType;
  next: (index: IndexType) => Promise<T>;
}

class CustumIterable<T, K> implements AsyncIterable<T> {
  private index = this.params.index;

  constructor(private params: ICustomIterableParams<T, K>) {}

  public [Symbol.asyncIterator](): AsyncIterator<T> {
    return { next: async () => this.next() };
  }

  private async next(): Promise<IteratorResult<T>> {
    const item = await this.params.next(this.index);
    this.index = this.params.nextIndex(this.index, item);
    return {
      done: item === undefined,
      value: item
    };
  }
}

/// Usage:

interface IDog {
  breed: string;
  age: number;
}

async function getDog(id: number): Promise<IDog> {
  const dogs: IDog[] = [
    { breed: "german shepherd", age: 2 },
    { breed: "labrador", age: 4 }
  ];
  return dogs[id] || undefined;
}

const dogIterable: AsyncIterable<IDog> = new CustumIterable<IDog, number>({
  index: 0,
  nextIndex: index => index + 1,
  next: index => getDog(index)
});

async function showDogs(): Promise<void> {
  for await (const dog of dogIterable) {
    console.log(dog);
  }
}

showDogs().catch(e => {
  throw new Error(e);
});