Ionic3 การนำ RxJS Operators มาช่วยในการ Binding Data ให้กับ View Components

Khomkrib Singh
PranWorks
Published in
5 min readAug 23, 2018

เขียนครั้งแรกเลยครับ ปกติเป็นคนที่พูดไม่ค่อยรู้เรื่อง เขียนออกมาจะรู้เรื่องไหม ลองมาดูกัน ไม่ค่อยถนัดเรื่องศัพท์เทคนิค ต่างๆนะ บอกไว้ก่อน 555+

ผิดพลาดอะไรตรงไหนขออภัยด้วยครับ

ม่ะ เริ่มมม….

ก่อนเริ่มมาดูกันก่อนบทความนี้มีอะไรบ้าง….

Overview:

  • Ionic คืออะไร
  • RxJS คืออะไร
  • Project Preview
  • ตัวอย่างการ Binding Data โดยใช้ RxJS Operators

Ionic คืออะไร

Ionic คือ Framework ที่ใช้ทำ Hybrid App, Ionicใช้การทำงานร่วมกันของ HTML, JavaScript, และ CSS เพื่อสร้าง Mobile Application ในรูปแบบของ WebView และใช้ Cordova ในการ build ตาม mobile platform ที่ต้องการ Ionic support (iOS, Android และ Window) และการ Implement ของตัว Ionic จะใช้ในรูปแบบของ Angular 5 ตอนนี้ Ionic มีถึง Ionic4 แล้วและใช้ Angular 6 ในการ implement มาพร้อมกับ feature ใหม่ๆเพียบ แต่บทความนี้จะใช้ Ionic3 ในการ Implement ครับ

ถึงจะเป็น Hybrid App ที่เป็น WebView แต่ก็สามารถเข้าถึง native function ต่างๆ เช่น กล้อง, Notification, Location และอื่นๆ โดยผ่าน npm packages ที่เรียกว่า ionic-native และ Cordova plugins ต่างๆ

RxJS คืออะไร?

อยากรู้ว่ามันคืออะไรจริงๆ จะต้องไปดูถึง Reactive Programming คืออะไรนู่นล่ะ เอาเป็นว่ามันคือ Reactive extension for JavaScript ที่ใช้ Observable ในการจัดการ asynchronous หรือ callback code ต่างๆ ละกัน >-<

เมื่อพูดถึง asynchronous, callback code อะไรพวกนี้ สิ่งที่เราใช้บ่อยๆ จะแว๊บเข้ามาในหัวคือไอ่เจ้า Promise นั่นเอง การเลือกใช้ Observable หรือ Promise นั้นให้ใช้ตามความเหมาะสมครับ

Observable & Promise functions

Project Preview

App Demo

Project ที่ใช้ในบทความนี้เป็น ทำขึ้นมาเพื่อเป็นการยกตัวอย่างการใช้ RxJS Operators มาช่วยในการ Binding Data ให้กับ View Components โดยใช้ข้อมูล Characters ในเรื่อง Star Wars จาก Star Wars API มาแสดง โดยการทำ HTTP GET Request และ Project นี้ทำการสร้างแบบ Lazy load page ทำให้การ Implement บางอย่างต่างจาก Project ที่สร้างมาจาก Ionic นิดหน่อย

สำหรับผู้ที่ มี Ionic3 ในเครื่องอยู่แล้ว Source Code Project นี้สามารถ Download มาลองได้ที่ GitHub: https://github.com/im-rookiez/myapp.git

ตัวอย่าง View Components ที่อยู่บน home.html

./pages/home/home.html

ในบทความนี้ จะแนะนำการใช้ RxJS Operators ในการ Binding Data ในส่วนของ component “<ion-searchbar>” และ CountConponent “<count></count>”

ก่อนอื่นเรามาดู Project Structure ใน ./src ก่อนละกันว่ามีอะไรบ้าง

./src project structure

เราจะ focus ไปที่ folders components, models และ providers

เริ่มจาก folder components ก่อนเลย มันใช้ทำอะไร?

มันคือที่เก็บไฟล์ต่างๆ ที่เป็นพวก component ที่ถูกใช้ ใน file.html ต่างๆ ที่มันถูกเรียกโดยใช้ <name> สีแดงๆ ตามตัวอย่าง home.html ด้านบน การเรียกใช้แบบนี้ทำให้ต่อการ reuse ใช้ใหม่กับหน้าอื่นๆได้

ส่วนไฟล์ที่ชื่อว่า components.module.ts นั้นเป็นไฟล์ไว้ export components ต่างๆที่เราทำไว้ เพื่อส่วนของ View สามารถนำไปใช้ได้โดยการ Import

ยกตัวอย่างไฟล์ ./components/count ว่าในนั้นมีอะไรบ้าง?

components/count

สังเกตว่าจะมีไฟล์ .html, .scss, .ts ให้เลย ไฟล์พวกนี้เราไม่จำเป็นต้องสร้างขึ้นมาเองนะครับ สามารถใช้ ionic cli command “ionic g component <name>” ได้เลยเพิ่มเติมเกี่ยวกับ ionic cli คลิก

ตัวอย่าง count.html

./components/count/count.html

เราสามารถสร้าง HTML เป็นส่วนเฉพาะของมันได้เลย ไม่ว่าจะเป็น HTML, CSS Class หรือ Data ต่างๆ ที่ใช้แสดง ทำให้เราไม่ต้องไป implement แบบนี้ในทุกที่ที่เราใช้ ใส่แค่ <count></count> แบบในรูปด้านบน home.html ก็เพียงพอแล้ว

ต่อไป models:

ตัวนี้ไม่มีอะไรมาก มี class ที่ชื่อว่า Character และ CharacterDetail ไว้ map response object ที่ส่งมาจากตัว HTTP request เฉยๆ

ตัวอย่างใน ./models/character.ts เทียบกับ response data จาก API

modal & response data

ต่อไปคือ providers:

ใน folder นี้จะเป็นศูนย์รวมของ class ที่เป็น injectable ต่างๆ รวมถึง class ที่ทำหน้าที่ รับ-ส่ง request กับ API ภายนอก

สังเกตว่าจะมี folder api, character, count และ message

api จะเป็นตัวรับหน้าที่เป็นปากทาง เข้า-ออก ในการ รับ-ส่ง ข้อมูลกับ API ภายนอก ใน Project นี้ใช้เพียง HTTP GET Request

ตัวอย่าง api.ts

api.ts

ใน api.ts ถูกเรียกใช้จาก provider อื่นๆ ที่ต้องการทำ HTTP Request อีกทีหนึ่ง และจะเห็นว่ามี การใช้ RxJS Operators “retry” ในการส่ง request ใหม่หากเกิด error

Provider อื่นๆ ที่เหลือจะเป็นตัว ระบุ api ที่ใช้ และทำการโต้ตอบกับ หน้า view component ที่เรียกใช้มันอีกที

แนะนำ Project ไปพลางๆ ละ กลับมาที่ การใช้ RxJS Operators ในการ Binding Data ในหน้า view ดีกว่า ต่อไปจะเป็นการยกตัวอย่าง view component ระหว่าง Search bar และ CountComponent ว่ามันทำงานร่วมกันอย่างไร และ Binding Data อย่างไร

ตัวอย่างการ Binding Data โดยใช้ RxJS Operators

เริ่มจาก Search bar

search bar

Search bar ที่ใช้นี้เป็นของ ionic UI component <ion-searchbar> เมื่อมี search query เข้ามา มันจะ call event ที่ชื่อว่า seachCharacter() ซึ่งถูก Implement ไว้ใน home.ts และใน function นี้จะเรียก function ของ CharacterProvider ที่ถูก Import เข้ามาเพื่อ รับ-ส่ง ข้อมูลจาก API

./pages/home/home.ts

ทีนี้เราก็จะได้ข้อมูลที่ search มาแสดงในหน้าจอแล้วล่ะ ผ่านตัว this.characters ว่าแต่ ไหน RxJS Operators ที่บอกว่าช่วย Binding Data…

มันไม่ได้ถูก Implement ใน home.ts ครับ มันอยู่ใน function ของ CharacterProvider ที่ชื่อ searchCharacters()

การทำเช่นนี้ทำให้เราแยกความสำคัญ และการจัดลำดับ code ในแต่ละส่วนได้ เช่น ./pages/home/home.ts สนใจแค่ value ที่ return มาจาก provider ก็พอ จะทำอะไรกับมันมาก่อนนั้น ไม่สนใจ ส่วนตัว provider เอง ก็มีหน้าที่ จัดการกับ request ว่าจะทำอะไรกับมันบ้าง ก่อนส่งไปให้ function ที่ต้องการต่อไป

./providers/character/character.ts

สังเกตได้ว่ามี RxJS Operators ถูกเรียกใช้ หลายตัว และนี่คือข้อดีอย่างหนึ่งของ การจัดการ asynchronous function โดยใช้ Obserable เพราะใน 1 request ที่ทำไปนั้นสามารถทำอะไรกับมันได้หลายอย่าง ก่อนจะมาถึงตัวแปรที่เราใช้รับค่าโดยไม่กระทบกับ Process หลักของการ request เลย

การ search 1 request มี RxJS Operators ที่ใช้อะไรบ้าง:

  • debounceTime: เมื่อมี data เข้ามาให้รอตามเวลาที่กำหนดไว้ก่อน จึงจะทำงานต่อไป
  • distinctUntilChanged: เมื่อ data ที่เข้ามามีค่าเท่ากับค่าก่อนหน้าจะไม่ทำการ request จนกว่า data จะถูกเปลี่ยนแปลง
  • tap: ใช้เป็นตัว call logging process ระหว่างการทำ HTTP request
  • catchError: เป็นการ throw error ที่เกิดขึ้นระหว่างการทำ HTTP request คล้ายกับ .catch() ของ Promise
  • map: เป็นตัวช่วยในการ assign ค่าต่างๆให้กับ response data ที่เข้ามา เช่นการ assign model class ให้ response object ดังรูปด้านบน (ได้ response object มาจัดการให้มันเป็น Type ของ Character ซะเลย เวลาเรียกใช้จะได้ง่ายๆ) แม้แต่การ Binding Data ให้กับ view component ดังที่อยู่ใน home.html ที่มีการแสดง “Result:” จำนวนทั้งหมดของ search result ที่ API return มาให้ หรือ จะเป็น Message “Data not found” ก็สามารถทำได้ โดยรับ data ผ่าน provider function ของ provider นั้นๆ ดังที่อธิบายไว้ด้านล่าง

this.count.getCountResult(character.results.length) เพื่อนำไป process และ แสดงผล ในรูปแบบของจำนวน “Result:”

this.message.showMessage(character) เพื่อนำไป process และแสดงผลในรูปแบบข้อความต่างๆ เช่น ใน กรณีที่ ไม่พบข้อมูลจะแสดง “Data not found” เป็นต้น

ตัว RxJS มีให้เลือกใช้มากมายสามารถเข้าไปศึกษาได้ที่ คลิก

ถัดมาเรามาดูกันว่า component ที่สร้างไว้มันรับค่าไปแสดงได้อย่างไร

ยกตัวอย่าง CountComponent <count></count>

เปิดไฟล์ ./components/components/count.ts ก่อนเลย

./components/components/count.ts

โล่งเลยใช่ไหมครับ 555+ มีเพียงการ Import provider และ ประกาศ injecter ใน contructor เท่านั้น ไฟล์นี้เป็นทางผ่านเพื่อเราจะได้ get ค่าจาก provider ให้ view comonent โดยตรงผ่าน public injector ที่ import มาในชื่อ CountProvider นั่นเอง

จากด้านบน เมื่อเราเรียกใช้ this.count.getCountResult(character.results.length) data ที่ถูกส่งเข้ามา จะถูก CountComponent นำไปแสดงอย่างไร ลองสังเกตค่าที่เรียกใช้บน view component และใน CountProvider ดูครับ

call CountProvider

หลังจากที่ function ถูกเรียกใช้งานแล้ว count.countResult จะถูก assign value ตาม function ที่ implement ไว้ใน CountProvider และ view component ที่มีการเรียกใช้ค่านี้อยู่ก็จะ update value ตาม (function ถูก call ปุ๊บ ตัวแปรที่ใช้งานอยู่ก็ update ปั๊บเลย)…

เพียงเท่านี้เราก็สามารถ Binding Data count.countResult เพื่อแสดงจำนวน search result ทั้งหมด มาแสดงบน view component ได้ตามที่เราต้องการแล้วล่ะครับ

“Note: การ Binding Data สามารถทำได้หลายวิธี เลือกได้ความเหมาะสม ของ Process งานนั้นๆ และวิธีที่ใช้ในบทความนี้เป็นเพียงทางเลือกนึงเท่านั้น…”

ขอบคุณครับ >-<

--

--