Subscription Angular là gì

--- Chỉnh sửa 4 - Tài nguyên bổ sung (2018/09/01)

Trong một tập gần đây của Adventures in Angular Ben Lesh và Ward Bell thảo luận về các vấn đề xung quanh cách thức / thời điểm hủy đăng ký thành phần. Cuộc thảo luận bắt đầu vào khoảng 1:05:30.

Ward đề cập right now there's an awful takeUntil dance that takes a lot of machineryvà Shai Reznik đề cập Angular handles some of the subscriptions like http and routing.

Đáp lại, Ben đề cập rằng có các cuộc thảo luận ngay bây giờ để cho phép các Đài quan sát móc vào các sự kiện vòng đời thành phần Angular và Ward gợi ý một sự kiện quan sát trong vòng đời mà một thành phần có thể đăng ký như một cách để biết khi nào hoàn thành Quan sát được duy trì như trạng thái bên trong thành phần.

Điều đó nói rằng, chúng ta chủ yếu cần các giải pháp ngay bây giờ vì vậy đây là một số tài nguyên khác.

Tôi đã đề cập trong một bình luận trên blog của Nicholas rằng việc sử dụng quá mức takeUntil()có thể là một dấu hiệu cho thấy thành phần của bạn đang cố gắng làm quá nhiều và nên tách các thành phần hiện có của bạn thành các thành phần Tính năngTrình bày . Sau đó, bạn có thể | asyncquan sát từ thành phần Tính năng thành một Inputthành phần Trình bày, có nghĩa là không cần đăng ký ở bất cứ đâu. Tìm hiểu thêm về phương pháp này ở đây

--- Chỉnh sửa 3 - Giải pháp 'Chính thức' (2017/04/09)

Tôi đã nói chuyện với Ward Bell về câu hỏi này tại NGConf (tôi thậm chí đã chỉ cho anh ấy câu trả lời mà anh ấy nói là đúng) nhưng anh ấy nói với tôi rằng nhóm tài liệu cho Angular có một giải pháp cho câu hỏi này chưa được công bố (mặc dù họ đang làm việc để được chấp thuận ). Ông cũng nói với tôi rằng tôi có thể cập nhật câu trả lời SO của mình với khuyến nghị chính thức sắp tới.

Giải pháp tất cả chúng ta nên sử dụng trong tương lai là thêm một private ngUnsubscribe = new Subject();trường vào tất cả các thành phần có .subscribe()lệnh gọi đến Observables trong mã lớp của chúng.

Chúng tôi sau đó gọi this.ngUnsubscribe.next(); this.ngUnsubscribe.complete();trong ngOnDestroy()phương pháp của chúng tôi .

Nước sốt bí mật (như đã được ghi nhận bởi @metamaker ) là gọi takeUntil(this.ngUnsubscribe)trước mỗi .subscribe()cuộc gọi của chúng tôi sẽ đảm bảo tất cả các đăng ký sẽ được dọn sạch khi thành phần bị phá hủy.

Thí dụ:

import { Component, OnDestroy, OnInit } from '@angular/core'; // RxJs 6.x+ import paths import { filter, startWith, takeUntil } from 'rxjs/operators'; import { Subject } from 'rxjs'; import { BookService } from '../books.service'; @Component({ selector: 'app-books', templateUrl: './books.component.html' }) export class BooksComponent implements OnDestroy, OnInit { private ngUnsubscribe = new Subject(); constructor(private booksService: BookService) { } ngOnInit() { this.booksService.getBooks() .pipe( startWith([]), filter(books => books.length > 0), takeUntil(this.ngUnsubscribe) ) .subscribe(books => console.log(books)); this.booksService.getArchivedBooks() .pipe(takeUntil(this.ngUnsubscribe)) .subscribe(archivedBooks => console.log(archivedBooks)); } ngOnDestroy() { this.ngUnsubscribe.next(); this.ngUnsubscribe.complete(); } }

Lưu ý: Điều quan trọng là thêm takeUntiltoán tử là cái cuối cùng để tránh rò rỉ với các vật quan sát trung gian trong chuỗi toán tử.

--- Chỉnh sửa 2 (2016/12/28)

Nguồn 5

Hướng dẫn Angular, chương Routing hiện nêu như sau: "Bộ định tuyến quản lý các thiết bị quan sát mà nó cung cấp và bản địa hóa các đăng ký. Các đăng ký được dọn sạch khi thành phần bị phá hủy, bảo vệ chống rò rỉ bộ nhớ, vì vậy chúng tôi không cần hủy đăng ký các thông số tuyến đường quan sát được. " - Mark Rajcok

Đây là một cuộc thảo luận về các vấn đề Github cho các tài liệu Angular liên quan đến Bộ quan sát Bộ định tuyến trong đó Ward Bell đề cập đến việc làm rõ tất cả những điều này đang được thực hiện.

--- Chỉnh sửa 1

Nguồn 4

Trong video này từ NgEurope Rob Wormald cũng nói rằng bạn không cần hủy đăng ký khỏi Bộ quan sát Bộ định tuyến. Ông cũng đề cập đến httpdịch vụ và ActivatedRoute.paramstrong video này từ tháng 11 năm 2016 .

--- Câu trả lời gốc

TLDR:

Đối với câu hỏi này, có (2) loại Observables- giá trị hữu hạn và giá trị vô hạn .

http Observablestạo ra các giá trị hữu hạn (1) và một cái gì đó giống như DOM event listener Observablestạo ra các giá trị vô hạn .

Nếu bạn gọi thủ công subscribe(không sử dụng ống async), thì unsubscribetừ vô hạn Observables .

Đừng lo lắng về những cái hữu hạn , RxJssẽ chăm sóc chúng.

Nguồn 1

Tôi đã theo dõi câu trả lời từ Rob Wormald trong Angular's Gitter tại đây .

Ông tuyên bố (tôi tổ chức lại cho rõ ràng và nhấn mạnh là của tôi)

nếu đó là một chuỗi giá trị đơn (như yêu cầu http) thì việc dọn dẹp thủ công là không cần thiết (giả sử bạn đăng ký trong bộ điều khiển theo cách thủ công)

tôi nên nói "nếu đó là một chuỗi hoàn thành " (trong đó các chuỗi giá trị đơn, a la http, là một)

nếu đó là một chuỗi vô hạn , bạn nên hủy đăng ký ống async nào cho bạn

Ngoài ra, ông còn đề cập đến video youtube này trên Đài quan sát rằng they clean up after themselves... trong bối cảnh của Đài quan sát complete(như Promise, luôn hoàn thành vì chúng luôn tạo ra 1 giá trị và kết thúc - chúng tôi không bao giờ lo lắng về việc hủy đăng ký từ Promise để đảm bảo chúng dọn sạch xhrsự kiện người nghe, phải không?).

Nguồn 2

Cũng trong hướng dẫn Rangle cho Angular 2, nó đọc

Trong hầu hết các trường hợp, chúng tôi sẽ không cần phải gọi một cách rõ ràng phương thức hủy đăng ký trừ khi chúng tôi muốn hủy sớm hoặc Observable của chúng tôi có tuổi thọ dài hơn đăng ký của chúng tôi. Hành vi mặc định của các nhà khai thác quan sát là loại bỏ đăng ký ngay khi các thông báo .complete () hoặc .error () được xuất bản. Hãy nhớ rằng RxJS được thiết kế để được sử dụng theo kiểu "lửa và quên" hầu hết thời gian.

Khi nào cụm từ our Observable has a longer lifespan than our subscriptionáp dụng?

Nó áp dụng khi đăng ký được tạo bên trong một thành phần bị hủy trước đó (hoặc không phải là "lâu" trước khi Observablehoàn thành.

Tôi đọc điều này có nghĩa là nếu chúng tôi đăng ký một httpyêu cầu hoặc có thể quan sát được phát ra 10 giá trị và thành phần của chúng tôi bị hủy trước khi httpyêu cầu đó trả về hoặc 10 giá trị đã được phát ra, chúng tôi vẫn ổn!

Khi yêu cầu trả về hoặc giá trị thứ 10 cuối cùng được phát ra, Observablenó sẽ hoàn thành và tất cả các tài nguyên sẽ được dọn sạch.

Nguồn 3

Nếu chúng ta nhìn vào ví dụ này so với cùng Rangle hướng dẫn chúng ta có thể thấy rằng Subscriptionđể route.paramskhông đòi hỏi một unsubscribe()bởi vì chúng ta không biết khi nào những paramssẽ ngừng thay đổi (phát ra những giá trị mới).

Thành phần này có thể bị phá hủy bằng cách điều hướng đi trong trường hợp thông số tuyến có thể vẫn sẽ thay đổi (chúng có thể thay đổi về mặt kỹ thuật cho đến khi ứng dụng kết thúc) và tài nguyên được phân bổ trong đăng ký vẫn sẽ được phân bổ vì chưa có completion.