hocvietcode.com
  • Trang chủ
  • Học lập trình
    • Lập trình C/C++
    • Lập trình HTML
    • Lập trình Javascript
      • Javascript cơ bản
      • ReactJS framework
      • AngularJS framework
      • Typescript cơ bản
      • Angular
    • Lập trình Mobile
      • Lập Trình Dart Cơ Bản
        • Dart Flutter Framework
    • Cơ sở dữ liệu
      • MySQL – MariaDB
      • Micrsoft SQL Server
      • Extensible Markup Language (XML)
      • JSON
    • Lập trình PHP
      • Lập trình PHP cơ bản
      • Laravel Framework
    • Lập trình Java
      • Java Cơ bản
    • Cấu trúc dữ liệu và giải thuật
    • Lập Trình C# Cơ Bản
    • Machine Learning
  • WORDPRESS
    • WordPress cơ bản
    • WordPress nâng cao
    • Chia sẻ WordPress
  • Kiến thức hệ thống
    • Microsoft Azure
    • Docker
    • Linux
  • Chia sẻ IT
    • Tin học văn phòng
      • Microsoft Word
      • Microsoft Excel
    • Marketing
      • Google Adwords
      • Facebook Ads
      • Kiến thức khác
    • Chia sẻ phần mềm
    • Review công nghệ
    • Công cụ – tiện ích
      • Kiểm tra bàn phím online
      • Kiểm tra webcam online
Đăng nhập
  • Đăng nhập / Đăng ký

Please enter key search to display results.

Home
  • Angular
  • Học lập trình
  • Lập trình Javascript
Giới thiệu Dependency Injection trong Angular

Giới thiệu Dependency Injection trong Angular

  • 25-12-2023
  • Toanngo92
  • 0 Comments

Mục lục

  • Dependency Injection là gì?
  • DI là gì?
  • Khởi tạo bên trong ProductComponent
  • Injection (Request để lấy về instance)
  • DI trong Angular
  • Override Provider trong Angular

Dependency Injection là gì?

Dependency Injection là một cách để tổ chức và quản lý các phần của một chương trình. Nó giúp chương trình linh hoạt hơn bằng cách cho phép chèn các thành phần cần thiết vào trong chương trình một cách dễ dàng. Bạn có thể nghĩ về nó như cách bạn sắp xếp và sử dụng các khối LEGO. Khi bạn cần một khối cụ thể, bạn lấy nó từ hộp và gắn vào nơi bạn cần trong cấu trúc của mô hình LEGO.

Trên Frontend, việc này cũng quan trọng và có ích. Ví dụ, Angular, một trong những Framework Frontend, sử dụng Dependency Injection rất nhiều. Nó có một cách riêng để chèn các phần tử vào chương trình, giúp tổ chức và quản lý chúng một cách dễ dàng hơn. Điều này giúp cho việc xây dựng ứng dụng một cách có tổ chức và linh hoạt hơn.

DI là gì?

Dependency Injection (DI) là cách để giúp các phần của chương trình “kết nối” với nhau một cách thông minh. Đây giống như việc khi bạn cần một công cụ nào đó, bạn không cần tự làm mà có thể nhờ người khác cung cấp cho bạn.

Ví dụ, hãy tưởng tượng bạn đang xây dựng một ứng dụng mua sắm trực tuyến. Bạn có các bộ phận khác nhau: một bộ phận quản lý sản phẩm, một bộ phận giỏ hàng và một bộ phận hiển thị sản phẩm. Thay vì mỗi bộ phận phải tự lo mọi việc, DI cho phép chúng “hỏi” và nhận các dịch vụ cần thiết từ nhau.

Ví dụ như khi phần hiển thị sản phẩm cần tính tổng giá trị giỏ hàng, nó không cần phải tự mình tính, mà có thể hỏi bộ phận giỏ hàng để lấy thông tin. Dependency Injection giúp cho các bộ phận này không phụ thuộc trực tiếp vào nhau mà có thể tương tác thông qua việc cung cấp cho nhau các dịch vụ cần thiết.

Hãy xem đoạn mã bên dưới

class ProductModel {
  sku: string;
  name: string;
  price: number;
}
interface CartItem {
  product: ProductModel;
  quantity: number;
}
class CartService {
  selectedProducts: CartItem[] = [];
  calculateTotal(): number {
    return this.selectedProducts.reduce(
      (total, item) => item.product.price * item.quantity + total,
      0
    );
  }
  addToCart(): void {
    // logic here
  }
}
class ProductComponent {
  cartService: CartService;
}

Khởi tạo bên trong ProductComponent

Trong một số trường hợp, để tạo một phiên bản của một công cụ trong một phần của chương trình từ phần khác, chúng ta có thể dùng lệnh “new”. Điều này giống như việc bạn tự làm một công cụ mới khi cần.

Ví dụ, trong một phần của chương trình, để có một dịch vụ giỏ hàng, chúng ta có thể viết mã để tạo một phiên bản mới của dịch vụ đó, giống như khi bạn tạo một chiếc đồ mới từ đầu. Điều này có thể như thế này:

class ProductComponent {
  cartService: CartService;
  constructor() {
    this.cartService = new CartService(); // Tạo một phiên bản mới của CartService
  }
}

Tuy nhiên, điều này có thể khiến hai phần của chương trình trở nên quá liên kết chặt chẽ với nhau (tight coupling). Khi bạn muốn thay đổi hoặc cải tiến dịch vụ giỏ hàng, bạn sẽ phải sửa code trong cả hai phần, và đôi khi còn phải kiểm tra lại cả hai để đảm bảo chúng vẫn hoạt động đúng.

Injection (Request để lấy về instance)

Injection, trong trường hợp này, giống như việc chúng ta đặt một yêu cầu đặc biệt để lấy một phiên bản cụ thể từ một nguồn nào đó.

Ví dụ, khi chúng ta cần một dịch vụ giỏ hàng trong một phần của chương trình, chúng ta không tạo một phiên bản mới mà chúng ta “yêu cầu” một phiên bản từ nguồn cung cấp (container) nào đó. Điều này có thể như sau:

class ProductComponent {
  cartService: CartService;
  constructor(cartService: CartService) {
    this.cartService = cartService; // Nhận dịch vụ giỏ hàng từ nguồn cung cấp
  }
}

Điều này có thể giúp chúng ta tạo ra một nguồn cung cấp tự động (IoC container) có khả năng cung cấp các phiên bản cần thiết cho các phần khác nhau của chương trình.

Thông qua cú pháp này, class ProductComponent không cần biết cách tạo dịch vụ giỏ hàng mà nó chỉ cần “yêu cầu” từ nguồn cung cấp. Khi muốn thay đổi hoặc cải tiến dịch vụ giỏ hàng, chúng ta chỉ cần thay đổi trong nguồn cung cấp mà không cần sửa code trong class ProductComponent. Điều này giúp chúng ta duy trì tính linh hoạt và dễ dàng thay đổi.

Mẫu thiết kế này gọi là Dependency Injection, cụ thể là constructor injection, giúp chúng ta quản lý và cung cấp các phiên bản cần thiết một cách thông minh.

DI trong Angular

Trong Angular, Dependency Injection (DI) bao gồm ba phần chính:

  1. Injector: Đây là một cái hộp chứa các công cụ để chúng ta lấy hoặc tạo các bản thể của các cái chúng ta cần.
  2. Provider: Như một bản vẽ chỉ dẫn cho Injector về cách tạo một bản thể của một cái gì đó.
  3. Dependency: Đại diện cho cái chúng ta cần tạo, có thể là một hàm, một giá trị cụ thể hoặc một object.

Chúng ta có thể cung cấp injectors với providers ở nhiều cấp độ khác nhau trong ứng dụng Angular:

  • Trong @Injectable() decorator cho một service.
  • Trong @NgModule() decorator (trong mảng providers) cho một NgModule.
  • Trong @Component() decorator (trong mảng providers) cho một component hoặc directive.

Ví dụ, để cung cấp CartService:

@Injectable({
  providedIn: "root",
})
export class CartService {
  // properties and methods
}

@Component({
  selector: "app-product",
  templateUrl: "./product.component.html",
  styleUrls: ["./product.component.css"],
})
export class ProductComponent implements OnInit {
  constructor(private cartService: CartService) {}

  ngOnInit() {
    console.log(this.cartService.calculateTotal());
  }
}

Khi chúng ta sử dụng @Injectable decorator, chúng ta đang cung cấp metadata cho Angular, cho biết cách để tạo một phiên bản của CartService khi được yêu cầu, như trong trường hợp của ProductComponent. Thông tin providedIn: 'root' chỉ ra rằng chúng ta muốn service này sẽ tồn tại như một bản thể duy nhất (singleton) trong toàn bộ ứng dụng.

Override Provider trong Angular

Bây giờ, thay vì lưu trữ thông tin giỏ hàng ở phía client như trước, hệ thống yêu cầu chúng ta sử dụng một nguồn thông tin bên ngoài như một API để thêm vào giỏ hàng và tính tổng tiền. Điều này yêu cầu chúng ta thay đổi cách thức tính toán trong class CartService, không thay đổi giao diện công khai của nó, chỉ là cách triển khai như sau:

@Injectable()
export class CartExtService {
  calculateTotal(): number {
    // Gọi đến nguồn dữ liệu bên ngoài
    // Trả về dữ liệu từ nguồn bên ngoài
    return Math.random() * 100;
  }
  addToCart(): void {
    // logic ở đây
  }
}

Điều tuyệt vời là chúng ta có thể thay đổi triển khai của CartService mà không cần phải sửa đổi code của ProductComponent. Có hai cách để làm điều này:

  1. Override thông qua @NgModule:
@NgModule({
  // các thông tin metadata khác
  providers: [
    {
      provide: CartService,
      useClass: CartExtService,
    },
  ],
})
export class AppModule {}

2. Hoặc Override trực tiếp trong @Injectable của service:

@Injectable({
  providedIn: "root",
  useClass: CartExtService,
})
export class CartService {
  // logic ở đây
}

Như vậy, thông qua cách làm này, chúng ta có thể thay đổi triển khai của CartService để sử dụng dịch vụ mới mà không làm ảnh hưởng đến code của ProductComponent, giúp chúng ta linh hoạt và dễ dàng thay đổi triển khai khi cần thiết.

Bài viết liên quan:

Sắp xếp sủi bọt – Bubble Sort
TypeScript với Kiểu Dữ Liệu Cơ Bản – 3
TypeScript với Kiểu Dữ Liệu Cơ Bản – 2
TypeScript với Kiểu Dữ Liệu Cơ Bản – 1
Typescript cơ bản và cách cài đặt cho người mới
Thực Hành Micro Frontends
Dynamic Component trong Angular
Async Validator trong Angular Form
Reactive Forms Trong Angular (Phần 2)
Reactive Forms Trong Angular (Phần 1)
Template-driven Forms Trong Angular (Phần 2)
Template-driven Forms Trong Angular (Phần 1)

THÊM BÌNH LUẬN Cancel reply

Dịch vụ thiết kế Wesbite

NỘI DUNG MỚI CẬP NHẬT

2. PHÂN TÍCH VÀ ĐẶC TẢ HỆ THỐNG

1. TỔNG QUAN KIẾN THỨC THỰC HÀNH TRIỂN KHAI DỰ ÁN CÔNG NGHỆ THÔNG TIN

Hướng dẫn tự cài đặt n8n comunity trên CyberPanel, trỏ tên miền

Mẫu prompt tạo mô tả chi tiết bối cảnh

Một số cải tiến trong ASP.NET Core, Razor Page, Model Binding, Gabbage collection

Giới thiệu

hocvietcode.com là website chia sẻ và cập nhật tin tức công nghệ, chia sẻ kiến thức, kỹ năng. Chúng tôi rất cảm ơn và mong muốn nhận được nhiều phản hồi để có thể phục vụ quý bạn đọc tốt hơn !

Liên hệ quảng cáo: [email protected]

Kết nối với HỌC VIẾT CODE

© hocvietcode.com - Tech888 Co .Ltd since 2019

Đăng nhập

Trở thành một phần của cộng đồng của chúng tôi!
Registration complete. Please check your email.
Đăng nhập bằng google
Đăng kýBạn quên mật khẩu?

Create an account

Welcome! Register for an account
The user name or email address is not correct.
Registration confirmation will be emailed to you.
Log in Lost your password?

Reset password

Recover your password
Password reset email has been sent.
The email could not be sent. Possible reason: your host may have disabled the mail function.
A password will be e-mailed to you.
Log in Register
×