TransWikia.com

Angular Typescript Async queue service

Code Review Asked by Leonel Franchelli on February 22, 2021

i’ve implemented a waiter service in Angular for syncronice multiple calls to one async function and i want to know if there exists a simplier way of atchiving the same result or if it’s over engineered

the code

import {Injectable} from '@angular/core';

export class PromiseRef {
  resolve: (any?: any) => any;
  reject: (any?: any) => any;
}

class ExecutionQueue {
  promises = new Set<PromiseRef>();
  lock: boolean = false;

  constructor() {
  }

  hasPromises(): boolean {
    return !!this.promises.size;
  }

  clearQueue() {
    this.lock = false;
    this.promises.clear();
  }

  add(promiseRef: PromiseRef) {
    this.promises.add(promiseRef);
  }

  remove(promiseRef: PromiseRef) {
    this.promises.delete(promiseRef);
  }
}

@Injectable({providedIn: 'root'})
export class WaiterService {

  private executionQueues = new Map<string, ExecutionQueue>();

  constructor() {
  }

  isLocked(queueName: string): boolean {
    return this.getQueue(queueName).lock;
  }

  lockQueue(queueName: string): Promise<PromiseRef> {
    return new Promise<PromiseRef>(
      (resolve, reject) => {
        const queue = this.getQueue(queueName);

        const promiseRef = new PromiseRef();

        promiseRef.resolve = resolve;
        promiseRef.reject = reject;

        if (!queue.lock) {
          queue.lock = true;
          promiseRef.resolve(promiseRef);
        } else {
          this.addToExecutionQueue(queueName, promiseRef);
        }
      }
    );
  }

  async unlockQueue(queueName: string) {
    const queue = this.getQueue(queueName);
    queue.lock = false;
    const iterator = queue.promises.values();
    const nextValue = iterator.next();

    if (nextValue.done) {
      return;
    }

    const promiseRef = nextValue.value;
    queue.remove(promiseRef);

    const newRef = await this.lockQueue(queueName);
    promiseRef.resolve(newRef);
  }

  addToExecutionQueue(queueName: string, promiseRef: PromiseRef) {
    const queue = this.getQueue(queueName);
    queue.add(promiseRef);
  }

  private getQueue(queueName: string) {
    let queue = this.executionQueues.get(queueName);

    if (!queue) {
      queue = new ExecutionQueue();
      this.executionQueues.set(queueName, queue);
    }

    return queue;
  }
}

then you should use it like this

async someFn() {
  await this.waiterService.lockQueue('a_queue');

  try {
    // do async stuff
  } finally {
    this.waiterService.unlockQueue('a_queue');
  }
}

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP