Pages

Wednesday, September 14, 2022

How to properly handle a heavy task asynchronously with JavaScript

Simple note for running heavy task asynchronously. The image below are the code in real-world I have written recently.


1) Write an async function with try catch, write down a txt file for tracking logs if needed.

2) Use for...of or normal for loop inside that async function.

3) Use await wait (any name here, does not matter) function (return promise implemented with setTimeout. You have to write this function yourself.

4) Never use forEach here, it does not work.

Thursday, August 18, 2022

Rxjs - handling multiple requests and subtle differences of respective operators and higher order observable

OPTION 1:  PARALLEL

You might use forkJoin or mergeMap.

1) forkJoin([observable 1, observable 2]): can only trigger if ALL observable completed. Input can be array or object of an observable.

=> Perfect if you have a couple number of HTTP requests or any kind of asynchronous operations. It works like Promise.all([]).


Demo here

Multiple request with mergeMap (see explanation below)




OPTION 2: SEQUENTIAL

concatMap (triggered by order)

 

some other combination operators: 

1) combineLatest([observable1, observable2]): just works without caring about the completion of streams. Input can be array or object of observable. It will be trigger if ONE of the streams emitting new value.

2) zip([observable1, observable2, observablen...]): Combine each corresponding data from different streams into one object/array.

See https://stackblitz.com/edit/typescript-5az27c?devtoolsheight=100&file=index.ts

3) concat 

Combine different observable one by after completion IN ORDER.

4) merge

Combine different observable and emit NOT IN ORDER

5) race : Reset the "circle" of emission each time it is completed.

6) withLatestForm (operator)

RxJS Higher Order Observables (HOOs):

(Receive Outer Observable ==> Emit/Return Inner Observable)

7) switchMap, mergeMap, concatMap, exhaustMap

switchMap    = switchAll + map
mergeMap    = mergeAll + map
concatMap    = concatAll + map
exhaustMap  = exhaustAll + map

Using these HOO, you don't have to use nested subscribe when you use nested observable.

- switchMap cancels previous HTTP requests that are still in progress, while mergeMap lets all of them finish.

concatMap does not subscribe to the next observable until the previous completes

- exhaustMap:  ignore other values until that observable completes.

Note: FlatMap is an alias of mergeMap

Example 1:  example
Example 2:  example 

10 common operators: 

map,  filter, tap, switchMap, concatMap, combineLatest, startWith, distinctUntilChanged, debounceTime,  catchError

Source: https://www.youtube.com/watch?v=Byttv3YpjQk&ab_channel=JoshuaMorony

References:

https://blog.angular-university.io/rxjs-higher-order-mapping/

https://riptutorial.com/rxjs/example/27973/sending-multiple-parallel-http-requests

https://indepth.dev/reference/rxjs/operators/merge-map

https://vdsabev.medium.com/the-simple-difference-between-rxjs-switchmap-and-mergemap-397c311552a5#

https://luukgruijs.medium.com/understanding-rxjs-map-mergemap-switchmap-and-concatmap-833fc1fb09ff#

https://www.youtube.com/playlist?list=PLxnmNhAZjt7y9u9xum0SIvz1_p09AP019

https://www.youtube.com/watch?v=qYdKmYp95Jg&ab_channel=DecodedFrontend

https://www.youtube.com/watch?v=qChj6nScvl0&ab_channel=ChauTran

https://github.com/angular-vietnam/100-days-of-angular/blob/master/Day025-rxjs-hoo-utility.md

https://www.youtube.com/watch?v=Byttv3YpjQk&ab_channel=JoshuaMorony

https://rxmarbles.com/

https://www.youtube.com/watch?v=ak3MvMn8u18


Wednesday, August 17, 2022

RXJS operator: toArray() - Combine individual value/item to an array

 The main different between "of" and "from" provided by Rxjs is that "of" emits all data once but "from" prints out data one by one rather than the whole sequence.

In case you use from() but still want to emit data in the form of an array, then toArray() is here to rescue.



Tuesday, August 16, 2022

Convert RXJS's observable to Promise and vice verse

In case you want to "mix" RXJS with promise-based approach, then firstValueForm or lastValueForm are here to rescue. Both can be imported from "rxjs" library.

See the code for converting observable to Promise. As await function can only be written inside an async function, you need to put them in a function started with the keyword async as normal.


What if you want to convert from promise to observable? Simply use "from(promise)" imported directly from "rxjs" and pass the promise as the parameter. Take a look at the following image:


The data is a promise-based one and returned from server using axios.

It is worth noting that both lastValueFrom() and firstValueFrom() can only get 1 emitted value. You might use async subscribe to get the whole data instead in case you want to use it somewhere else. Take a look at the image below:



FYI toPromise() is being deprecated in RxJS 7 and will be removed in RxJS 8

Saturday, July 2, 2022

Publish Angular-based app to Netlify - Fix 404

 While I have no issue when attempting to publish React or Vue-based app to Netlify, there is a tiny configuration that is needed when you push and deploy code to this platform.

Running "ng build" will generate a folder often named "dist" and a (another) nested folder named as "my-app" (You might change it for sure but that is the one by default). So you need to configure as follows so that Netlify can successfully launch your page.


Netlify verion: https://vietnameselanguage.netlify.app/

Vercel.com version https://vietnameselanguage.org

Wednesday, June 8, 2022

@ViewChild in Angular

Using display:none in Angular does not completely remove the elements in the DOM. It is still there and ready to be "re-active" using JavaScript. So you need *ngIf if in this case.

When conditional rendering data using *ngIf in Angular (>=2), you cannot query the DOM inside and at the same time appending something to those elements inside. 

You might need to use the decorator @ViewChild() such as in follows: 

 @ViewChild('control_bottom_html')  control_bottom_variable: ElementRef;

You need to declare  #control_bottom_html (with the hashtag) in the DOM where you want to manipulate directly whereas control_bottom_variable is the variable that can be then used to update the DOM already injected. 

Now inside the phrase  ngAfterViewInit() (not the phrase ngOnInit()) , you can call query the div injected with #control_bottom_html.

 this.controlPanel = this.control_bottom_variable.nativeElement; 

Then you can manipulate it such as appending elements or implements events.

From Angular Docs, it seems that you should use Render2 rather than ElementRef for safety reason.

https://angular.io/api/core/ElementRef

Thursday, January 6, 2022

Rescuing a WordPress-based site on Amazon LightSail and moving to another VPS

Don't get me wrong, Amazon LightSail is one of the most affordable VPS services out there.  A big name such as Amazon might give you the feeling of stability, reliability, and so forth. I have no complaint at all so far as my clients are happy with that.

Yet, they still want to move the servers closer to their customers, and given that Amazon is still not available in Vietnam yet, it becomes a new mission. Turn out the limitation of the VPS in terms of CPU and RAM might give me another kind of headache. Normally, I have no problem with moving the site to a new server especially in the case of WordPress as there are tons of already-built plugins on the market.

So "rescuing" in this post simply means it seems impossible to backup a WordPress with a limited source VPS (say 1GB of RAM).

Here are the defined steps I often do to clone and move a WordPress-based website using the Duplicator plugin.

1) Updating WordPress and all active plugins. Remove inactive ones.

2) Clone the current site using Duplicator.

3) Upload the package issued by Duplicator on a brand new VPS and then run installer.php (this file is given by Duplicator). During this process, you will have to create a new database on the new VPS.

4) Make some changes if needed.

However, the above process does not work well as Duplicator cannot clone the whole website when the RAM of the current VPS is limited. And this time it hurt me badly.


Here are what I did to handle it.

1) Cloned the current VPS on LightSail using the snapshot feature and then restored on a new computer with higher resources (4GB of RAM for example).

2) Run Duplicator. This time it worked

3) Following the above steps to restore the package given by Duplicator.

4) Check the site and then change DNS on Cloudflare.

5) Check new DNS via https://check-host.net/ or https://dnschecker.org/

6) Note: for those who are using aapanel, you might need to fix the 404 error as nginx does not handle the .htaccess file. 

location / {

    # file ($uri) or directory ($uri/)? if not, redirect to /index.php + query string

    try_files $uri $uri/ /index.php?$args;

    index  index.html index.htm index.php;

}

Take a look at the following image:

FYI: In case you use Plesk, then you might take advantage of the Migration feature which allows you to clone and restore your server to another one in a few minutes. I might write another post about that.

Friday, December 24, 2021

Notes when installing WireGuard VPN with Docker (Portainer) and wg-easy

Here are some notices when attempting to install a secure and fast VPN with WireGuard.

- WireGuard and Outline are both great, easy to install on both servers and clients no matter what. If you are familiar with Docker, you can deploy it with a few clicks.

I tried to give WireGuard a shot. The most elegant way to deploy a docker-based container is by implementing Portainer. FYI, Portainer is built by Auckland guys.

PORTAINER WAY: You can simply hit some clicks to customize the ports and configure authentication with Portainer. The docker image on the Docker hub is given below: 

https://hub.docker.com/r/weejewel/wg-easy

COMMAND LINE WAY: You can also install docker using the command `docker-composer up` as usual if you prefer to terminal. The nice thing is that you can also do that within Portainer. So Portainer wins, definitely.

https://raw.githubusercontent.com/WeeJeWel/wg-easy/master/docker-compose.yml


Image: I installed Dante shock5, Outline, and WireGuard on the same, cheap VPS

Noted that you should open two ports 51821 (TCP) and 51820 (UDP) for VPN. You can find this detailed information in the file docker-compose.yml mentioned above.

      - "51820:51820/udp" ----> CRITICAL INFORMATION SHOULD BE NOTED

      - "51821:51821/tcp" ----> CRITICAL INFORMATION SHOULD BE NOTED

You also need to replace your public IP address within the file docker-compose.yml.

It appears that wg-easy cannot be installed on an ARM-based chip. As far as I know, go-lang seems not wholely support this kind of CPU.

My first impression is that it runs really fast and it is easy to configure WireGuard on mobile devices. So after logging to WireGuard via port 51821 (say http://your_public_id_address:51821), you can CRUD a new profile and then give it to your friends if you wish.

Yet, installing WireGuard as a client on Ubuntu seems to take time. Here are some links: 

 https://www.thomas-krenn.com/en/wiki/Ubuntu_Desktop_as_WireGuard_VPN_client_configuration

https://tech.serhatteker.com/post/2021-01/how-to-set-up-wireguard-client-on-ubuntu-desktop/

Todo list: I am thinking about installing nginx proxy manager to manage WireGuard via accessing a real domain. But it does not matter much. FYI: WireGuard is really fast and does not take much CPU or RAM.


PS: It seems that using the traditional method (command-line based) with docker-compose up -d is the workable way to install WireGuard. Then I used Portainer to manage it with a breeze. Normally Portainer serves me pretty well but somehow this time I cannot install WireGuard via this great UI tool frequently used to manage docker. Yet, I can still use this for monitoring WireGuard.

FYI: You might need to add MU value to the server's configuration as discussed here, another one and there.

MTU = 1280 (client, say Ubuntu desktop)

[Add the line MTU = 1280 in the wireguard server interface at: /etc/wireguard/wg0.conf if you are using Ubuntu server]

Updated: I can now install WireGuard with Portainer. You might need to make some changes regarding the right to trigger WireGuard. So NET_ADMIN should be granted.

Updated: Installing Wireguard on Ubuntu client is much much easier than I think. 

1) First, download the configuration file from WireGuard UI above.

2) Install WireGuard on the Ubuntu client.

3) Rename the file above to wg0.conf and put to /etc/wireguard/wg0.conf'

4) Run sudo wg-quick up wg0

5) Check your newest IP with ip2location.com or through sudo wg

Don't forget sudo wg-quick down wg0 if you want to turn the VPN off.

Updated: Watchtower is not recommended to use just in case you want to update docker as it breaks the configuration. 


Friday, December 3, 2021

Khế ước ngẫu nhiên

 Để tạo một số ngẫu nhiên từ 0 tới x, ta phải nhân số cực trên, chính là x, với Math.random().

Giả sử x là hai từ/tiếng đầu tiên trong Kiều, như người ta nói, đời người, số random kia ắt sẽ mỗi người một phận, đã được destined đặt trong khế ước nào đấy, nếu có, với thượng đế.

Nếu có ai đó, như mệ, mà cuộc đời ưu ái thương tặng con số random ấy lớn hơn số cực đại kia, thì cũng là ơn riêng.

Xin vĩnh biệt mệ, người vẫn hay cho chúng tôi những con cá khô mỗi lần giáp hạt.

Trên đời lại vắng một người thỉnh thoảng hỏi tôi, hế lô, chúng mày kiếm ăn ra sao. À, ý là cần cá khô thì mần răng tao không biết, cứ mò về với ngôi nhà có rặng phi lao nhé.

Ai cũng ngơ ngác. Con mèo chắc cũng thế, khi căn nhà bắt đầu vắng tiếng ai đó…

Biển đang cuộn sóng. Nước quanh làng lềnh phềnh. Góc nhà, một bịch cá khô lủ khủ vẫn lủng lẳng bất cần. À, cho những đứa nào cần nhé. Của mệ đấy.


Thursday, May 20, 2021

Covid vào thành

 Nổi tiếng nhất huyện tôi là Chí Phèo. Nổi tiếng nhất làng tôi là Tạ Biên Cương.

Giờ làng nổi lềnh phềnh trên mặt báo vì Covid 19. Ngày thứ hai bị phong tỏa với gần chục ca. Sáng nay, sau khi một cháu lớp đệ nhất dương tính, cả lớp cháu mấy chục bé rồng rắn tí xíu "lên đường" cách li 21 ngày. Bố mẹ nước mắt trông theo. Biết làm sao.

Tôi cũng không biết phải làm sao. Chỉ mong tất cả mọi người bình tĩnh và bình an. Sinh ra và lớn lên ở làng, bạn sẽ như có họ với tất cả mọi người vậy.

Mẹ tôi chắc lại nói, đấy, ma quỷ con ạ. Có thể covid là một trò đùa của Thanos với mã vạch 69X. Mà kệ nó đi mẹ ạ. Mẹ cứ ở trong nhà với đàn gà là được. Thóc còn rất nhiều đúng không ?