Orange Pi Ubuntu 20 LTS Increase Zram/Swap Size

By default Orange Pi Lite is coming with 512 Mb zram/swap which makes it impossible to compile anything heavy on it. You can increase zram size to 1024 Mb with following steps.

sudo swapoff /dev/zram1
sudo zramctl --reset /dev/zram1
sudo zramctl --find --size 1024M # You can also set to 2 GB = 2048, 4 GB = 4096
sudo mkswap /dev/zram1
sudo swapon /dev/zram1 -p 5

You can check it now.

sudo swapon --show
free -h

More information about zramctl can be found here: http://manpages.ubuntu.com/manpages/focal/man8/zramctl.8.html

Express.js Customize the Error Page of JSON Errors

Assume that we are getting a request in JSON format and we don’t want to hit the default error page of express.json() middleware.

Instead we may want to send a specific JSON response back in case if JSON that we get is not valid.

We can check the body of requests with the following middleware.

// requestCheck.middleware.js
const requestCheckMiddleware = (err,req,res,next) => {
  if (res.headersSent) {
     next(err); 
     return;
  }
  if (req.body) {
    return res.status(400).json({ message:'Malformed JSON.' });
  }
}

module.exports = requestCheckMiddleware;

We can use that middleware globally or in our route exactly like that:

...
const requestCheckMiddleware = require('./requestCheck.middleware');
...
app.use(express.json());
//enable globally with app.use(requestCheckMiddleware) or use route based...
app.post('/post', requestCheckMiddleware, (req,res) => {
     res.json({ message: 'Body is a valid JSON.' });
});

Angular Communication Between Components

First example is from parent to child.

// parent.component.ts 

export class ParentComponent implements OnInit {

  textVarFromParent = 'Text to be passed to child component';

  ngOnInit(): void {
  }

}
// parent.component.html

<app-child [text]="textVarFromParent"></app-child>
// child.component.ts

export class ChildComponent implements OnInit {

  constructor () { }

  @Input() text: string;

  ngOnInit() { }
}
// child.component.html

{{ text }}

Child to parent.

// child.component.ts

export class ChildComponent implements OnInit {

  constructor() { }

  @Output() text = new EventEmitter<string>();

  ngOnInit(): void {
    this.text.emit('text from child');
  }

}
// app.component.html

<app-child (text)="textVarFromChild"></app-child>
// parent.component.ts

export class ParentComponent implements OnInit, OnChanges {

  textVarFromChild: string;

  ngOnChanges(): void {
    console.log(this.textVarFromChild);
  }

  ngOnInit(): void {
  }
}

More complex example.

// child.component.ts 

export class ChildComponent implements OnInit {

  constructor() { }

  @Output() text = new EventEmitter<string>();

  changeText(value: string) {
    console.log('From child component:' + value);
    this.text.emit(value);
  }

  ngOnInit(): void {
  }

}
// child.component.html

<button (click)="changeText('changed')">Change Text</button>
// parent.component.ts 

export class ParentComponent implements OnInit {

  changeText(value: string) {
    console.log('Parent component:' + value);
  }

  ngOnInit(): void {

  }
}
// parent.component.html

<app-child (text)="changeText($event)"></app-child>

Angular Async Pipe – Unsubscribe (Best Practices 2)

Use async pipe or unsubscribe properly.

For example if you ignite a http get request by visiting X component and then route to Y component without waiting your get request to complete, your get request in X component still runs.

There are several ways to handle that issue. First one is, using async pipe. Async pipe automatically unsubscribes when you change your route.

//example.component.ts

export class ExampleComponent implements OnInit {

    constructor(private http: HttpClient) { }
  
    recipes: Observable<any[]>;
  
    ngOnInit(): void {
      this.recipes = this.http.get<any[]>("URL").pipe();
    }
  
  }
// example.component.html

<ul>
<li *ngFor="let recipe of recipes | async">{{ recipe.title }}</li>
</ul>

Second way is to use unsubscribe in ngOnDestroy method.

export class ExampleComponent implements OnInit, OnDestroy {

    constructor(private http: HttpClient) { }
  
    subscription;
  
    ngOnDestroy(): void {
     this.subscription.unsubscribe();
    }
  
    ngOnInit(): void {
      this.subscription = this.http.get<any[]>("URL").subscribe();
    }
  
  }

Third way is to use subjects of RxJS.

export class ExampleComponent implements OnInit, OnDestroy {

  constructor(private http: HttpClient) { }

  unsubscribeSubject = new Subject();

  ngOnDestroy(): void {
   this.unsubscribeSubject.next();
   this.unsubscribeSubject.complete();
  }

  ngOnInit(): void {
    this.http.get<any[]>("URL")
    .pipe(takeUntil(this.unsubscribeSubject)).subscribe();
  }

}

Angular 9 Subscribe in Subscribe (Best Practices 1)

In some cases, for example you may need to get userId from httpclient request then use that userId in another client request. Well, if you’re a beginner you will think about to handle it in subscribe in subscribe.

Do not use subscribe in subscribe. Use mergeMap instead.

Here is my model file including Todo and User model.

// models.model.ts

export interface Todo {
    userId: number;
    id: number;
    title: string;
    completed: boolean;
}

export interface User {
    id: number;
    name: string;
    username: string;
    email: string;
    address: {
       street: string;
       suite: string;
       city: string;
       zipcode: string;
       geo: {
           lat: string;
           lng: string;
       }
    };
    phone: string;
    website: string;
    company: {
        name: string;
        catchPhrase: string;
        bs: string;
    };
}

My component which is using mergeMap.

// myapp/myapp.component.ts

import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { mergeMap } from 'rxjs/operators';

import { Todo, User } from '../models.model';

@Component({
selector: 'app-myapp',
templateUrl: './myapp.component.html',
styleUrls: ['./myapp.component.css']
})

export class MyappComponent implements OnInit {

constructor(private http: HttpClient) { }

todo: Todo;
user: User;

ngOnInit(): void {
this.http.get<Todo>('https://jsonplaceholder.typicode.com/todos/1')
.pipe(mergeMap((todo: Todo) => this.http.get<User>(`https://jsonplaceholder.typicode.com/users/${todo.userId}`))
)
.subscribe((user: User) => this.user = user);
}
}
    {{ user.id }}
    {{ user.name }}
    {{ user.username }}
    {{ user.email }}
    {{ user.address.city }}
    {{ user.address.geo.lat }}