javascript - Nhược điểm của subjects khi dùng asObservable
Chào, tôi thực sự đang nghi ngờ về việc sử dụng lời gọi "asObserveable()" trên subject.
Theo quan điểm của tôi, nó tạo ra một chi phí không cần thiết lớn. Việc ngăn chặn các cuộc gọi như "next()" hoặc "complete()" theo quan điểm của tôi là vô ích.
Bạn có thể nêu cho tôi một lý do chính đáng tại sao bạn nên làm việc này không?
Chỉ cần so sánh hai cái này
- Không có
export class TestService {
public get test$(): Observable<test> {
return this.test$.asObservable();
}
public get test2$(): Observable<test> {
return this.test2$.asObservable();
}
public get test3$(): Observable<test3> {
return this.test3$.asObservable();
}
public get test4$(): Observable<test4> {
return this.test4$.asObservable();
}
private readonly _test1$ = new ReplaySubject<test1>(1);
private readonly _test2$ = new ReplaySubject<test2>(1);
private readonly _test3$ = new ReplaySubject<test3>(1);
private readonly _test4$ = new ReplaySubject<test4>(1);
}
- Không có
export class TestService {
public readonly test1$ = new ReplaySubject<test1>(1);
public readonly test2$ = new ReplaySubject<test2>(1);
public readonly test3$ = new ReplaySubject<test3>(1);
public readonly test4$ = new ReplaySubject<test4>(1);
}
Câu trả lời #1
Những hạn chế của subject's asObservable
Một số mã mẫu. Không nhiều thứ khác.
Theo quan điểm của tôi, nó tạo ra một gánh nặng không cần thiết lớn.
Bạn đã đo nó chưa? Các đối tượng mở rộng Observables, tất cả những gì nó làm là tạo một bản sao nông. Tôi sẽ ngạc nhiên nếu bạn tìm thấy một ứng dụng nơi sự khác biệt lớn hơn phương sai (thực chất là không thể đo được).
Ưu điểm của subject's asObservable
Một kiến trúc sạch hơn có nghĩa là dễ dàng hơn để tìm lỗi và/hoặc dễ dàng ngăn các lỗi được tạo ra ngay từ đầu.
Đóng gói là một trong những nguyên tắc cơ bản của kiến trúc sạch. Vì đóng gói che giấu một số phần của chương trình khỏi các phần khác, nó làm cho mỗi phần trở nên dễ suy nghĩ hơn một chút. Do đó, nó dễ hiểu, dễ viết, dễ mở rộng và dễ bảo trì hơn.
Nếu có một lỗi trong một hệ thống được thiết kế tốt, diện tích bề mặt sẽ nhỏ hơn nhiều.
Nói chung, lợi ích của những quyết định kiểu này thường trở nên rõ ràng hơn đối với các dự án lớn với các đội nhóm lớn hơn. Nếu bạn đang viết một dự án giải trí tại nhà hoặc tạo ra một sản phẩm khả thi tối thiểu một mình hoặc với một nhóm nhỏ, có thể sẽ hợp lý khi bỏ qua việc lập kế hoạch quá kỹ để thúc đẩy tiến độ. Một dự án như vậy có thể cần được viết lại/tái cấu trúc khi nó phát triển, nhưng đến lúc đó, công sức bỏ thêm sẽ xứng đáng.
Các lựa chọn thay thế cho Subject's asObservable
Nếu bạn có một trình kiểm tra kiểu tĩnh được đặt tương đối nghiêm ngặt (TypeScript, Elm, PureScript, ClojureScript, v.v.), thì bạn có thể chỉ cần trả về Subject dưới dạng Observable mà không cần thực hiện bất kỳ thay đổi nào đối với biểu diễn thời gian chạy của kiểu.
Bạn có được sự đóng gói mà không tốn chi phí thời gian chạy.
Câu trả lời #2
Tôi có thể đưa ra một lý do chính đáng. Giả sử, bạn muốn phát ra một số sự kiện execCompleted$ dựa trên một hành động nhất định. Đây là cách nó được triển khai
export class TestService {
private readonly execCompleted$ = new Subject<string>();
public async makeServerCall(userData){
const resp = await this.http.post('...').toPromise();
this.execCompleted$.next(resp.data.id);
return resp;
}
public getUpdatedId(){
this.execCompleted$.asObservable();
}
}
Hiện nay, dịch vụ này được sử dụng bởi hai thành phần -> Admin và UserInfo.
Thành phần Admin có thể cập nhật một số thông tin người dùng bằng cách sử dụng makeServerCall() và cập nhật một số dữ liệu người dùng. Sự kiện này phải được UserInfoComponent bắt để nó có thể lắng nghe và cập nhật thông tin (sau khi một số cập nhật đã được thực hiện).
Bằng cách phơi bày Subject sử dụng getUpdatedId(), bạn đang hạn chế bất kỳ thành phần nào khác gửi nhầm sự kiện next() trên execCompleted$. Subject này chỉ được kích hoạt khi makeServerCall(userData) được gọi.
Đây chỉ là một ví dụ đơn giản. Có những trường hợp phức tạp hơn nhưng tất cả đều có cùng một ý định cơ bản.
Không để các sự kiện không mong muốn được phát ra hoặc bị hủy. Chỉ nguồn dự định mới nên làm điều đó.
Đây là một thực hành tiêu chuẩn trong lập trình, nơi bạn muốn có một số hạn chế về những gì có thể được mở rộng bởi người khác và những gì không thể. Giống như nguyên tắc mở-đóng.
