การใช้งาน Observable (of , observable, delay)

Tawan_Ait
5 min readNov 19, 2020

--

เอาไว้มาจัดการกับ Data ที่จะเข้ามา จากต่าง Component กัน โดยเราจะใช้ Observeable มาจัดการ เพื่อไปประมวลต่อไป

ตัวอย่าง เริ่มต้นสร้างโปรเจคชื่อ rxjs-test (ที่ Terminal)

ng new rxjs-test
cd rxjs-test
code .
ng serve

หลังจากนั้นลบหน้า Template ออกให้หมด และเอาตัวแปร data เรื่องมาแสดงที่หน้า Template ที่ไฟล์ app.component.html พร้อมประกาศค่าให้ตัวแปร data = ‘Hello’ ที่ไฟล์ app.component.ts บันทึกแล้วไปดูที่ Browser

จากนั้น เราจะเปลี่ยนให้ตัวแปร data ให้เป็น Observable มี Type เป็น number ที่ไฟล์ app.component.ts

data : Observable<number>

เมื่อรันแล้วจะติด error แบบนี้ เพราะที่หน้า Template เพราะไม่ได้เปลี่ยนpipe | uppercase เป็น pipe | async

รู้แล้วๆๆ เราก็ไปเปลี่ยนให้เป็น pipe | async ที่ไฟล์ app.component.html แล้วเราจะได้ผลลัพธ์ อย่างที่ตั้งใจเอาไว้ คือเราจะเห็นค่าที่เราได้กำหนดเอาไว้ที่ Browser

<h1>{{data | async}}</h1>

และเราต้องการให้นับตัวเลขไปเรื่อย บวกเพิ่มทีละ 1 ด้วยการเพิ่มอีก 2 ตัวแปร ตัวแปร i เพื่อมาเป็นตัวเริ่มต้น และตัวแปร loop เก็บค่าการบวกเพิ่ม ที่ไฟล์ app.component.ts

i = 1;
loop: any;
ngOnInit(){
this.loop = setInterval(()=> {
this.data = of(this.i++)
}, 1000)
}

หลังจาก ตัวแปรมี loop ค่าของตัวเลข เพิ่มขึ้นเรื่อยๆ แล้ว ก็อยากจะสร้างปุ่ม เพื่อมา Stop ไม่ให้นับต่อ และให้ Start หลังจาก Stop

เราตรงไปที่ไฟล์ app.component.html ก่อนเลยและเพิ่ม ปุ่ม เข้าไปสองปุ่ม

<button (click)="stop()">STOP</button>
<button (click)="start()">START</button>

แล้วเราไปเขียน Method start() ให้ตัวแปร loop เท่ากับ setInterval และ ให้ตัวแปร data เท่ากับ i บวกเพิ่มทีละ 1 ทุกๆ 1 วินาที

และ Method stop() สั่งให้ เคลียค่า ของตัวแปร loop ที่ไฟล์ app.component.ts

start(){
this.loop = setInterval(()=> {
this.data = of(this.i++)
}, 1000)
}
stop(){
clearInterval(this.loop)
}

แล้วเราจะสามารถกดปุ่มเพื่อสั่งให้ Start และ Stop ได้แล้ว

เริ่มเข้าเรื่อง

ต่อจากนี้เราจะเริ่มมาเข้าเรื่องกันล่ะ ที่อยากจะกรอก Data มาจากอีกที่ให้กับอีกที่ เหมือนที่เราเกริ่นๆ ตอนแรกว่าข้าม Component กันนั่นแหล่ะ

อันดับแรกเราจะสร้าง Component มาเพิ่ม 2 Component เพื่อให้ทั้งสองได้ส่ง Data ไปหากัน พร้อมกับสร้างตัวกลางมาหนึ่งตัว คือ Service ที่เอาให้ทั้ง 2 Component ได้คุยกันผ่าน Service ตัวนี้

Component 2 Component และ 1 Service ด้วยคำสั่งนี้ ชื่อว่า

ng g c home
ng g c counter
ng g s send-data

จากที่เราได้สร้าง Component เสร็จแล้วเราจะย้าย Script ที่เป็นส่วนของการนับ มาไว้ที่ Component ชื่อ CounterComponent ดังนี้

และเราจะทำ Routing เพื่อให้ Link ไปยัง Component ที่เรากำหนดเมื่อเรากดปุ่ม ไปที่ไฟล์ app-routing.module.ts

{path:'home', component: HomeComponent},
{path: 'counter', component: CounterComponent},

เสร็จแล้วเราจะไปสร้าง Link ไว้ที่หน้า Template เพื่อให้คลิกแล้ว link ไปยังหน้านั้นๆ ไปที่ไฟล์ app.component.html และมีการตกแต่งนิดหน่อยที่ไฟล์ app.component.css

*** ที่สำคัญอย่าลืมใส่ router-outlet เพื่อให้สามารถ link หากันได้

<router-outlet></router-outlet>

เสร็จแล้วลองรันดู จะได้หน้าแบบนี้ Browser

สร้างที่สำหรับกรอก Data และเมื่อกดปุ่ม จะส่ง Data ไปยัง CounterComponent ไปที่ไฟล์ home.component.html

จากนั้นไปที่ไฟล์ home.component.ts เพื่อเขียนตัวแปร ที่รับค่าใหม่เมื่อกรอก เข้ามา จาก Template พร้อมกับสร้าง Method click(){} ว่าเมื่อคลิกแล้วจะส่งข้อมูลไปไหน ??

inputCounter = new FormControl(1)
click(){}

และไปที่ไฟล์ app.module.ts เพื่อ import : ReactiveFormModule เข้ามาเพื่อใช้งาน FormControl ให้สามารถรับ-ส่งค่าได้

ReactiveFormModule

จากนั้น เราจะเขียน service มาเพื่อเป็นตัวกลางในการติดต่อกับแต่ละ component ไว้ให้เรียกใช้งาน ตามที่แต่ละ component ต้องการที่จะทำอะไร

อย่างเช่นที่จะทำคือ เราจะกรอกค่าจาก HomeComponent แล้วเอาค่านั้นส่งไปให้ CounterComponent คำนวณต่อไป

ตรงไปที่ไฟล์ send-data.service.ts ประกาศตัวแปร subject เป็น Private ใช้เฉพาะที่นี้เท่านั้น เพื่อเก็บค่าใหม่ (ค่าที่ได้จากการกระทำ) และประกาศตัวแปร observer ที่มีค่าเท่ากับ ตัวแปร subject และยังสังเกตพฤติกรรมด้วย (สังเกตการทำงาน)

private subject =  new BehaviorSubject(0);
observer = this.subject.asObservable()

จากนั้นเราจะเขียน Method ใหม่มา 2 ตัว คือ set() และ get() เพื่อกำหนดค่า และ เพื่อเอาค่านั้นออกมาดู ดังนี้

set(data: number){
this.subject.next(data)
}
get():number {
return this.subject.value
}

OK จากที่เราเขียน Service เสร็จแล้ว เราจะย้อนกลับไปที่ไฟล์ home.component.ts เพื่อเขียน Method click() ว่าเมื่อคลิกแล้วจะให้ส่ง data ผ่านทาง Service ไปให้กับ CounterComponent

ประกาศตัวแปร sender ที่มีค่าเท่ากับชื่อ Service : SendDataService แบบ private

และ เขียน Method click() ที่มีตัวแปร data เท่ากับ ค่าที่กรอกเข้ามา และ กำหนดค่าให้กับ service Method set()

private sender : SendDataService,click(){
const data = this.inputCounter.value
this.sender.set(data)
}

เมื่อฝั่งนี้ส่งไปแล้ว เราต้องการให้อีก component นำไปใช้งาน เราจะย้อนไปที่ไฟล์ counter.component.ts เพื่อเรียกใช้ service เหมือนกัน แต่จะเขียนต่างออกไป เพราะเป็นตัวรับ ก็จะคอยฟัง data จากที่ฝั่งด้วยคำสั่ง subscribe() จากนั้นค่อยเอา Data ไปคำนวณต่อ

ประกาศตัวแปร sender ที่มีค่าเท่ากับชื่อ Service : SendDataService แบบ private

และชี้ไปยัง service sender ให้คอยฝั่ง data และให้ i เท่ากับ ค่าที่กรอกเข้ามาแทนค่าที่ได้กำหนดไว้แล้ว

private sender :SendDataService,this.sender.observer.subscribe(()=>{
this.i = this.sender.get()
})

จากนั้นบันทึก และไปดูที่ Broeser ของตัวเอง เมื่อกรอกค่าเสร็จแล้วกดปุ่ม CLICK สลับกลับไปที่ เมนู COUNTER กดปุ่ม START จะเห็นว่าเขาจะเริ่มที่ค่าที่เรากรอกเข้ามา

ขอบคุณ Teacher ของอิฉัน เข้าใจเท่านี้เลยจริงๆ 555+

--

--

No responses yet