Angular Service มาจากไหน ใครเป็นคนสร้างให้เรา

Tanakrit Saisillapee
Zarewoft
Published in
2 min readNov 24, 2018

ใครที่เขียน Angular อยู่คงจะคุ้นชินกันกับการเรียกใช้เจ้า service ผ่านทาง constructor แบบนี้

code แสดงการ inject ผ่านทาง constructor ของ class

สงสัยกันไหมครับว่า เอ๊ะ? เราแค่บอกว่า constructor มี parameter เป็น class นี้ แล้วเราก็ใช้มันได้เลย แล้วใครเป็นคนสร้าง object ของ class นี้แล้วส่งเข้ามาให้เราละ?

ใครเป็นคนสร้าง?

ในโลกของ Angular มีสิ่งนึงที่เรียกว่า Injector ครับ ซึ่งความหมายตามพจนานุกรมของ Injector คือ

นี่ก็ตรงไป

แปลว่าหัวฉีดหรือตัวฉีด สิ่งที่มันทำก็ตรงตามความหมายเลยครับ คือมันเป็นตัวฉีดของที่เราต้องการให้ ซึ่งการจะให้ Injector ส่งของให้เราได้มี 2 อย่างที่เราต้องทำครับ

  1. เราต้องบอก Injector ว่ามี service อะไรบ้างที่ Injector จะต้องรู้จัก เพื่อเวลาที่มีใครมาขอจะได้เอาของให้ได้ถูก
  2. หมดแล้วครับ

ถ้าใครที่เขียน Angular มาตั้งแต่ดึกดำบรรพ์ (ไม่นับ AngularJS นะครับ) จะคุ้นชินกับเจ้า option ของ NgModule ที่ชื่อ provider

code แสดงการ register class provider ลงใน NgModule

เจ้า provider นี่ละครับที่เป็นตัวบอก injector ว่า “แกถือ service นี้อยู่นะ ถ้าใครมาขอก็ให้สร้างของจาก class นี้ให้เค้า” จากข้อความนี้จะเห็นว่าจริงๆแล้วตอนเราบอก Injector ว่าเค้าถืออะไรมันจะมี 2 ส่วนครับ ส่วนแรกคือ ชื่อ หรือ token ที่เอาไว้ใช้ระบุว่า dependency ชื่ออะไร กับวิธีการสร้างของที่ต้องส่งให้เวลามีคนมาขอ ถ้าเราเขียนการ register service ในรูปเต็มๆจะเป็น

code แสดงการ register class provider แบบเต็มลงใน NgModule

ดูจากโค้ดจะเห็นว่าจริงๆเรา register อะไรลงไปก็ได้ ให้คืนค่าอะไรก็ได้ แต่ถ้าเรา register class มันก็จะเข้าใจว่า “อ้อ ชื่อนี้สร้างของจาก class นี้ให้เอง” ดูวิธีการ register อย่างอื่นนอกเหนือจาก class ได้จากบทความนี้หรือ document ของ Angular ได้เลยครับ

เราใช้ท่าประกาศ provider แบบนี้กันมาเรื่อยๆจนถึง Angular เวอร์ชั่น 6 ก็มีคนบอกว่า “เฮ้นาย ท่านี้มันทำให้เขย่าต้นไม้ไม่ได้นะ (tree shaking คือการเช็คว่าของถูกใช้ป่าว ถ้าไม่ใช้ก็ไม่เอามา compile)” ที่มันใช้ไม่ได้เพราะว่า Angular ไม่สามารถเข้าไปคุ้ยหาโค้ดเราเพื่อดูว่าตัวไหนถูกใช้ไม่ถูกใช้ทั้งหมดได้ครับ เลยมีท่าใหม่ออกมา จากที่เราต้องเอา service ไป register ที่ module กลายเป็นให้เราบอกที่ service เลยว่า “ตัวฉันเองนี่ขึ้นตรงต่อใคร” อ๋า!

code แสดงการ register provider ภายใน service

ใน providedIn เราสามารถใส่ root เพื่อ register service ในระดับ application-wide (Injector ตัวสูงสุด จะพูดถึงในบทความถัดไปนะจ๊ะ) หรือใส่ class ของ module ก็ได้หากเราต้องการ register ในระดับ module นั้นๆ

สองท่านี้ไม่ได้มีท่าไหนดีกว่าท่าไหนนะครับ ทั้งสองท่าสามารถใช้ได้แล้วแต่ตามสถานะการณ์

ของที่ Injector ฉีดให้คนอื่นถ้ามันต้องถูกสร้างขึ้นมา อย่างเช่นถ้ามีคนบอกว่าขอ SomeService สิ่งที่ Injector ต้องส่งให้คือ instance ของ class นั้น เมื่อ Injector สร้างของที่ผูกกับ token ใดๆขึ้นมาแล้วของชิ้นนั้นจะไม่ถูกสร้างใหม่อีกเลยในอายุขัยของ Injector แปลว่าถ้ามีใครขอของจาก Injector ตัวเดียวกันจะได้ของชิ้นเดียวกัน

ถ้ามีใครขอของจาก Injector ตัวเดียวกันจะได้ของชิ้นเดียวกัน

แล้วของที่ Injector ถือถูกสร้างเมื่อไหร่ละ?

เมื่อมีใครเรียกขอของตัวนั้นครับ ถ้าขอไปแล้ว Injector คุ้ยดูในถังแล้วไม่เจอของก็จะสร้างขึ้นมาใหม่ให้ แต่ถ้าคุ้ยเจอว่ามีสร้างไว้แล้วก็จะส่งตัวนั้นกลับไปให้เลย

Can you feel it

จบเลี้ยวจ้า

ขอทิ้งท้ายบทความนี้ด้วยรูปสรุป Dependency Injection ใน Angular นะครับ

ใครทำรูปนี้ได้สวยกว่านี้ช่วยส่งมาทีครัช

--

--

Tanakrit Saisillapee
Zarewoft

Polyglot developer who ❤️ modular and simplicity. 👨🏻‍💻 at Zarewoft.