<p><strong>Be sure to open the console to see script output.</strong></p>
<hr/>
<p>If you find this demo useful, please consider <a href="https://www.paypal.me/RobertGravelle/1" target="_blank">donating $1 dollar</a> (secure PayPal link) for a coffee or purchasing one of my songs from <a href="https://ax.itunes.apple.com/WebObjects/MZSearch.woa/wa/search?term=rob%20gravelle" target="_blank">iTunes.com</a> or <a href="http://www.amazon.com/s/ref=ntt_srch_drd_B001ES9TTK?ie=UTF8&field-keywords=Rob%20Gravelle&index=digital-music&search-type=ss" target="_blank">Amazon.com</a> for only 0.99 cents each.</p>
<p>Rob uses and recommends <a href="http://www.mochahost.com/2425.html" target="_blank">MochaHost</a>, which provides Web Hosting for as low as $1.95 per month, as well as unlimited emails and disk space!</p>
import { Observable, timer } from "https://cdn.skypack.dev/rxjs";
import { retryWhen, tap, delayWhen, take } from "https://cdn.skypack.dev/rxjs/operators";

type UserSettings = { 
  settings: {
    viewType: number, 
    isLimited?: boolean 
  }
};

enum ViewSelectionValues {
  circle,
  table
}

class UserSettingsException extends Error {
  constructor(status: number, message: String) {
    super(message);
    // Ensure the name of this error is the same as the class name
    this.name = this.constructor.name;
    this.status = status;
    
    // Set the prototype explicitly.
    Object.setPrototypeOf(this, UserSettingsException.prototype);
  }
}


class UserService {
  constructor() {
    this.userSettingsMap = new Map([
      [
        "1234",
        {
          settings: {
            viewType: ViewSelectionValues.circle,
            isLimited: false
          }
        }
      ],
      [
        "3456", 
        {
          settings: {
            viewType: ViewSelectionValues.table,
            isLimited: true
          }
        }
      ]
    ]); 
  }

  getSettings(userid: String) {
    return new Observable(observable => {
      setTimeout(() => {
        if (userid === "9999") {
          console.log("Throwing error.");
          observable.error(
            new UserSettingsException(999, "An error occured!")
          );
        } else if (userid === "retry") {
          console.log("Throwing error for retry.");
          observable.error(
            new UserSettingsException(666, "An error occured!")
          );
        } else if (this.userSettingsMap.has(userid)) {
          observable.next(this.userSettingsMap.get(userid));
        } else {
          console.log("User not found.");
          observable.error(
            new UserSettingsException(404, "User " + userid + " not found.")
          );
        }
      }, 2000);
    });
  }
}

class Client {
  constructor(userid) {
    this.userid = userid;
    this.userService = new UserService();
    this.setViewType();
  }

  setViewType() {
    let retryAttempts = 0;
    this.userService.getSettings(this.userid)
    .pipe(
      retryWhen(errors => 
        errors.pipe(
          delayWhen(() => {
            console.log(`Retry attempt #${++retryAttempts}`);
            return timer(2000);
          }), 
          take(3)
        )
      )
    ) 
    .subscribe(userSettings => {
      console.log(userSettings.settings.viewType, userSettings.settings.isLimited);
      this.viewType = 
        userSettings.settings['viewType'] || ViewSelectionValues.circle;
      console.log("Got viewType: " + this.viewType);
    },
    error => {
      console.log(error.message);  
      this.viewType = ViewSelectionValues.circle;
      if (error.status && error.status !== 404) {
        throw error;
      }
    });
  }
}
console.log("Starting demo.");
console.log("Creating client 1234.");
let client = new Client('1234');

console.log("Creating new client with no settings yet.");
client = new Client('4444');

console.log("Creating client 3456.");
client = new Client('3456');

console.log("Creating error client.");
client = new Client('9999');

console.log("Creating retry client.");
client = new Client('retry');
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.1.0/rxjs.umd.min.js