Tạo đăng ký một lần


182

Tôi cần phải tạo một thuê bao cho một Observablecái được xử lý ngay lập tức khi nó được gọi lần đầu tiên.

Có cái gì đó như:

observable.subscribeOnce(func);

Trường hợp sử dụng của tôi, tôi đang tạo một thuê bao trong một trình xử lý tuyến tốc hành và đăng ký đang được gọi nhiều lần cho mỗi yêu cầu.

Câu trả lời:


319

Không chắc chắn 100% về những gì bạn cần, nhưng nếu bạn chỉ muốn quan sát giá trị đầu tiên, thì hãy sử dụng first()hoặc take(1):

observable.first().subscribe(func);

lưu ý: .take(1).first()cả hai hủy đăng ký tự động khi điều kiện của họ được đáp ứng

Cập nhật từ RxJS 5.5+

Từ nhận xét của Coderer .

import { first } from 'rxjs/operators'

observable
  .pipe(first())
  .subscribe(func);

Đây là lý do tại sao


33
Đăng ký có được tự động làm sạch sau?
Berkeley Martinez

50
Có nó làm. Lấy và đầu tiên cả hai hủy đăng ký khi điều kiện của họ được đáp ứng.
Brandon

20
Tại sao tài liệu không nói rằng nó tự động loại bỏ đăng ký?
jzig 15/03/2016

17
Đó là một quy tắc RxJS chung rằng các đăng ký được xử lý khi một luồng có thể quan sát kết thúc. Điều đó có nghĩa là bất kỳ toán tử nào "rút ngắn" một luồng (hoặc biến nó thành một loại luồng khác) sẽ hủy đăng ký khỏi luồng nguồn khi hoạt động của chúng hoàn tất. Tôi không chắc chắn nơi này hoặc nếu điều này được nêu trong tài liệu.
Brandon

37
Nếu bất cứ ai đến với điều này trong năm 2018, bạn thực sự muốn observable.pipe(first()).subscribe(func), firstđến từ đâu rxjs/operators.
Bộ giải mã

32

RxJS có một số tài liệu tốt nhất mà tôi từng gặp. Theo liên kết dưới đây sẽ đưa bạn đến một trường hợp sử dụng ánh xạ bảng cực kỳ hữu ích cho các toán tử. Ví dụ, dưới sự "Tôi muốn lấy giá trị đầu tiên" trường hợp sử dụng là ba nhà khai thác: first, firstOrDefault, và sample.

Lưu ý, nếu một chuỗi có thể quan sát hoàn thành mà không có thông báo, thì firstnhà điều hành sẽ thông báo cho người đăng ký có lỗi trong khi firstOrDefaultnhà điều hành cung cấp một giá trị mặc định cho người đăng ký.

nhà điều hành sử dụng tra cứu trường hợp


3

Nếu bạn muốn gọi một Đài quan sát chỉ một lần, điều đó có nghĩa là bạn sẽ không chờ đợi một luồng từ nó. Vì vậy, sử dụng toPromise()thay vì subscribe()sẽ là đủ trong trường hợp của bạn vì toPromise()không cần hủy đăng ký.


rất thú vị, điều này cũng có nghĩa là chúng ta có thể chỉ awaitsự promisemà làm cho nó trở thành một lót
Louie Almeda

@LouieAlmeda bạn có thể cho chúng tôi một ví dụ về lót không?
Ado Ren

Xin chào @AdoRen, tôi đã giải thích kỹ thuật này trong câu trả lời cho bạn, tôi hy vọng điều đó có ích.
Louie Almeda

2

Để bổ sung câu trả lời của @ Brandon , sử dụng first()hoặc tương tự cũng rất cần thiết để cập nhật BehaviorSubjectdựa trên câu trả lờiObservable . Ví dụ: chưa được kiểm tra):

var subject = new BehaviorSubject({1:'apple',2:'banana'});
var observable = subject.asObservable();

observable
  .pipe(
    first(), // <-- Ensures no stack overflow
    flatMap(function(obj) {
      obj[3] = 'pear';
      return of(obj);
    })
  )
  .subscribe(function(obj) {
    subject.next(obj);
  });

2

Phiên bản sạch và tiện lợi

Mở rộng trên câu trả lời tuyệt vời của M Fuat NUROĞLU về việc chuyển đổi quan sát thành lời hứa, đây là phiên bản rất tiện lợi của nó.

const value = await observable.toPromise();

console.log(value)

Cái hay của việc này là chúng ta có thể sử dụng giá trị đó như một biến thông thường mà không cần đưa vào một khối lồng nhau khác!

Điều này đặc biệt hữu ích khi bạn cần nhận được nhiều giá trị từ nhiều vật quan sát. Gọn gàng và sạch sẽ.

const content = await contentObservable.toPromise();
const isAuthenticated = await isAuthenticatedObservable.toPromise();

if(isAuthenticated){
   service.foo(content)
}

Tất nhiên, bạn sẽ phải thực hiện chức năng chứa của mình asyncnếu bạn đi với tuyến đường này. Bạn cũng có thể chỉ .thenlà lời hứa nếu bạn không muốn chức năng chứa không đồng bộ

Tôi không chắc chắn nếu có sự đánh đổi với phương pháp này, vui lòng cho tôi biết trong các nhận xét để chúng tôi biết.

PS Nếu bạn thích câu trả lời này, đừng quên nâng cấp câu trả lời của M Fuat NUROĞLU :)


0

Tôi đã có câu hỏi tương tự.

Dưới đây được gọi là thậm chí sau này từ các thay đổi trạng thái khác nhau. Như tôi không muốn.

function foo() {
    // this was called many times which was not needed
    observable.subscribe(func);
    changeObservableState("new value");
}

Tôi quyết định thử unsubscribe()sau khi đăng ký như dưới đây.

function foo() {
    // this was called ONE TIME
    observable.subscribe(func).unsubscribe();
    changeObservableState("new value");
}

subscribe(func).unsubscribe();cũng giống như subscribeOnce(func).

Tôi hy vọng điều đó đã giúp bạn quá.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.