Sunday, April 22, 2018

Angular Asynchronous programming I - made simple

  One big advantage of using modern Javascript framework like Angular or library like ReactJS is asynchronous programming following Observable pattern. If you and your organization is OK with calling a heavy Soap Web Service and feel OK to see the mouse cursor spinning when waiting for the Web Service to respond back, no worry, you can skip this topic and continue with it. If you are fed up with such cursor spinning and want to see some snappy page rendering, read on...
  I will share with you my experiences on Asynchronous programming in the next couple of post. This post is a simple model using Observable pattern.
  First thing first, we need to define the event source - Subject. In Observable pattern, the source will produce the source event and data and broadcast it to subscribers who are interested in such topic and registered themselves as subscribers to such data and change event.

Step 1) Run ng command: ng g service message; this will create message.service.ts and message.service.spec.ts. Put following code in message.service.ts:

import {Injectable} from '@angular/core';
import {Observable} from 'rxjs/Observable';
import {Subject} from 'rxjs/Subject';

@Injectable()
export class MessageService {
  message: Subject<string> = null;

  constructor() {
    this.message = new Subject<string>();
  }

  /**
   * Send an message
   *
   * Ao Bie 12/09/2017
   */
  sendMessage(message: string) {
    if (message) {
      this.message.next(message);
      console.log('service sending' + message);
    }
  }

  /**
   * Clear message
   *
   * Ao Bie 12/09/2017
   */
  clearMessage() {
    this.message.next();
  }

  /**
   * Get message so that the subscriber can get a handle
   *
   * Ao Bie 12/09/2017
   */
  getMessage(): Observable<string> {
    return this.message.asObservable();
  }

}


What does sendMessage do, it is sending a string text message. Once sendMessage gets called, the subscribers will be notified of this new message.

Step 2) Put below logic in your component ts file:

import {Component, OnInit, OnDestroy} from '@angular/core';
import {Subscription} from 'rxjs/Subscription';
import {MessageService} from '../message-service.service';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit, OnDestroy {
  message: string = null;
  subscription: Subscription;

  constructor(private messageService: MessageService) {
    this.subscription = this.messageService.getMessage().subscribe(
      message => {
        console.log('header got message: ' + message);
        this.message = message;
      }

    );
  }

  ngOnInit() {
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }

}

In the constructor, we inject the newly created service instance and subscribe this component to the subject in message service. When you subscribe to the Observable, you also provide your call back logic to handle the new data when being notified of latest chage. Above block in bold is the call back logic.

Be sure to unsubscribe in ngOnDestroy, otherwise you will observe memory leak when you run your web application.

Step 3) in another component ts file, catch the value entered from UI and broadcast this new value:

import {Component, OnInit} from '@angular/core';
import {MessageService} from '../message-service.service';


@Component({
  selector: 'app-work-pane',
  templateUrl: './work-pane.component.html',
  styleUrls: ['./work-pane.component.css']
})
export class WorkPaneComponent implements OnInit {


  constructor(private messageService: MessageService) {}

  ngOnInit() {
  }

  obSubmit(form: any) {

  }

  /**
   * Enter Message
   *
   * Ao Bie 12/09/2017
   */
  onEnterValue(event: any) {
    console.log('onEnterValue: ' + event.target.value);
    this.messageService.sendMessage(event.target.value);
//    return false;
  }

}

Logic inside onEnterValue is using service object to broadcast the new change entered from UI. The latest data will be broadcasted and all the registered subscribers will be notified.

Just this simple, you will know what to do in the header.component.html if you finish this post and want to test it out.