Skip to content
  • Home
  • Code
  • iOS & Swift
  • Combine
  • RxSwift
  • SwiftUI
  • Flutter & Dart
  • Tutorials
  • Art
  • Blog
Fx Studio
  • Home
  • Code
  • iOS & Swift
  • Combine
  • RxSwift
  • SwiftUI
  • Flutter & Dart
  • Tutorials
  • Art
  • Blog
Written by chuotfx on September 23, 2020

RxSwift – Combining Operators

RxSwift

Contents

  • Chuẩn bị
  • Combining Operators
  • 1. Prefixing and concatenating
    • 1.1. startWith
    • 1.2. Observable.concat
    • 1.3. concat
    • 1.4. concatMap
  • 2. Merging
  • 3. Combining elements
    • 3.1. combineLatest
    • 3.2. combineLatest(_:_:resultSelector:)
    • 3.3. zip
  • 4. Trigger
    • 4.1. withLatestFrom
    • 4.2. sample
  • 5. Switches
    • 5.1. amb
    • 5.2. switchLatest
  • 6. Combining elements within a sequence
    • 6.1. reduce
    • 6.2. scan(_:accumulator:)
  • Tạm kết

Chào bạn đến với Fx Studio. Bài viết này vẫn là chủ đề liên quan tới các Operators trong thế giới RxSwift. Nhóm toán tử đề cập đến lần này là Combining Operators.

Dành một chút thời gian để quay về các khái niệm cơ bản của Operators trong RxSwift. Và dành cho các bạn mới tiếp cận thì có thể tham khảo lại link sau:

    • RxSwift – Tìm hiểu Operators & Hello world!

Chuẩn bị

    • Xcode 11
    • Swift 5
    • Playground

Vẫn là em Playground huyền thoại. Chúng ta vẫn còn dùng tới nó để demo code cho bài viết này. Bạn chỉ cần tạo mới 1 file Playground từ project mà đã cài đặt ngay từ bài đầu của series. Bạn có thể checkout code lại đây.

Combining Operators

Bạn đã đi qua rất nhiều thứ trong RxSwift, từ bài đầu tiên trong series mệt mỏi này của Fx Studio rồi. Và mình có thể tóm gọn lại như sau:

Tạo & Lọc

Giờ chúng ta sẽ đi tới phần kết hợp. Có nhiều thứ chúng ta có thể kết hợp lại với nhau. Từ mặt dữ liệu tới đối tượng hoặc các stream … Đây cũng là những toán tử mà bạn sẽ phải dùng nhiều trong việc triển khai các logic trong project.

Chúng ta sẽ đi vào chi tiết các toán được sử dụng phổ biến với chức năng Combining.

1. Prefixing and concatenating

1.1. startWith

Đôi lúc chúng ta cần thêm một/nhiều phần tử trước khi Observable bắt đầu emit dữ liệu đi. Để làm gì, thì tuỳ ý bạn. Có khi đơn giản chỉ là muốn nó luôn có 1 giá trị nào đó lúc đầu tiên thôi. Toán tử này là startWith

Tham số truyền vào chính là giá trị mà có cùng kiểu giá trị với phần tử của Observable phát đi.

Ví dụ đoạn code sau:

    let bag = DisposeBag()
    
    Observable.of("B", "C", "D", "E")
        .startWith("A")
        .subscribe(onNext: { value in
            print(value)
        })
        .disposed(by: bag)

Bạn sẽ thấy, với Observable phát ra các giá trị bắt đầu từ B. Thì để chèn thêm 1 phần tử ở trước ta dùng toán tử startWith và thêm A vào. Kết quả ra như sau:

A
B
C
D
E

Quá EZ!

1.2. Observable.concat

Trước tiên thì bạn hãy ví dụ cho toán tử mới này.

    let bag = DisposeBag()
    
    let first = Observable.of(1, 2, 3)
    let second = Observable.of(4, 5, 6)

    let observable = Observable.concat([first, second])

    observable
        .subscribe(onNext: { value in
            print(value)
        })
        .disposed(by: bag)

Bạn sẽ nhận ra là Observable được tạo ra từ toán tử concat , thì có 1 tham số là 1 array Observable. Thử chạy kết quả xem như thế nào.

1
2
3
4
5
6

Tới đây thì bạn cũng hiểu ra rồi. concat sẽ nối các phần tử của nhiều sequence observable lại với nhau. Lại EZ nữa rồi!

1.3. concat

Bạn xem qua sơ đồ sau về toán tử Observable.concat.

Toán tử ở phần trên là một phương thức tạo Observable từ việc nối nhiều Observable lại với nhau. Còn đây là toán tử concat dùng với 1 đối tượng Observable. Nó sẽ nối các phần tử của một đối tượng Observable khác vào.

Phương pháp này giúp bạn có thêm 1 lúc nhiều phần tử, khắc phục nhược điểm của phần 1.

Code ví dụ như sau:

    let bag = DisposeBag()
    
    let first = Observable.of("A", "B", "C")
    let second = Observable.of("D", "E", "F")
    
    let observable = first.concat(second)
    
    observable
        .subscribe(onNext: { value in
            print(value)
        })
        .disposed(by: bag)

Ta dùng first.concat với tham số là second. Kết quả in ra như sau:

A
B
C
D
E
F

Cũng khá là đơn giản phải không nào. Đặc điểm của toán tử này là sử dụng cho 1 đối tượng Observable.

Chú ý: Toán tử concat này sẽ đợi Observable gốc hoàn thành. Thì sau đó Observable thứ 2 sẽ tiếp tục được nối vào.

1.4. concatMap

Lại là một toán tử concat đến từ nhóm toán tử Combining Operators. Và chúng ta xem sơ đồ mô tả nó như thế nào.

Khi có từ map trong tên của 1 toán tử, thì bạn cũng sẽ rằng sẽ có sự biến đổi về kiểu dữ liệu ở đây. Toán tử này đảm bảo việc các chuỗi được đóng lại trước khi chuỗi tiếp theo được đăng kí vào. Đảm vảo thứ tự trình tự.

Ở hình trên thì mô tả như sau:

  • Hình tròn là 1 Observable
  • Hình thoi là giá trị được phát ra cho Subscriber
  • Luật trong toán tử là cứ 1 Observable sẽ phát ra 2 dữ liệu hình thoi

Còn sau đây là code ví dụ:

    let bag = DisposeBag()
    
    let cities = [ "Mien Bac" : Observable.of("Ha Noi", "Hai Phong"),
                   "Mien Trung" : Observable.of("Hue", "Da Nang"),
                   "Mien Nam" : Observable.of("Ho Chi Minh", "Can Tho")]
    
    let observable = Observable.of("Mien Bac", "Mien Trung", "Mien Nam")
        .concatMap { name in
            cities[name] ?? .empty()
        }
    
    observable
        .subscribe(onNext: { (value) in
            print(value)
        })
        .disposed(by: bag)

Trong đó

  • cities là một Dictionary với key là String và value là 1 Observable
  • Tạo ra 1 Observable với kiểu dữ liệu cho phần tử là String
  • Dùng concatMap để biến đổi từ String thành String. Tuy nhiên có sự can thiệp là nối các chuỗi thuộc value của Dictionary trên lại với nhau

Kết quả ra như sau:

Ha Noi
Hai Phong
Hue
Da Nang
Ho Chi Minh
Can Tho

Cũng khá là không đơn giản phải không nào. Nói chung tụi này sẽ xoay vòng với nhau thôi. Chúng ta tiếp tục với nhóm tiếp theo.

2. Merging

Toán tử đầu tiên chính là merge. Cái tên cũng nói lên tất cả rồi. Và đặc điểm của toán tử này như sau:

  • merge sẽ tạo ra 1 Observable mới, khi một Observable có các element kiểu là Observable
  • Observable của merge sẽ kết thúc khi tất cả đều kết thúc
  • Nó không quan tâm tới thứ tự các Observable được thêm vào. Nên nếu có bất cứ phần tử nào từ các Observable đó phát đi thì Subscriber cũng đều nhận được

Code ví dụ như sau:

    let bag = DisposeBag()
    
    let chu = PublishSubject<String>()
    let so = PublishSubject<String>()
    
    let source = Observable.of(chu.asObserver(), so.asObserver())
    
    let observable = source.merge()
    
    observable
        .subscribe(onNext: { (value) in
            print(value)
        })
        .disposed(by: bag)
    
    chu.onNext("Một")
    so.onNext("1")
    chu.onNext("Hai")
    so.onNext("2")
    chu.onNext("Ba")
    so.onCompleted()
    so.onNext("3")
    chu.onNext("Bốn")
    chu.onCompleted()

Trong đó:

  • chu & so là 2 Subject, chịu trách nhiệm phát đi dữ liệu
  • source được tạo ra từ 2 Observable chu & so . Nó là 1 Observable
  • observable được tạo ra bằng toán tử merge
  • Vẫn subscribe như bình thường
  • Việc phát dữ liệu được thực hiện xen kẻ

Kết quả như sau:

Một
1
Hai
2
Ba
Bốn

Và tất nhiên bạn có thể hạn chế được số lượng các Observable được phép merge vào thông qua tham số .merge(maxConcurrent:)

3. Combining elements

Phần này là sẽ tới các toán tử kết hợp trong nhóm Combining Operators. Tên của tụi nó lèn nhèn thật!

3.1. combineLatest

Thông qua sơ đồ mô tả toán tử combineLatest , toán tử này sẽ phát đi những giá trị là sự kết hợp của các cặp giá trị mới nhất của từng Observable. Để hình dung cụ thể, ta qua từng bước ví dụ sau đây:

  • Tạo các Observable, sẽ phát dữ liệu đi. Có thể không theo thứ tự.
    let chu = PublishSubject<String>()
    let so = PublishSubject<String>()
  • Sử dụng combinedLatest với 2 Observable trên. Sau đó tiến hành subscribe như bình thường.
    let observable = Observable.combineLatest(chu, so)
    
    observable
        .subscribe(onNext: { (value) in
            print(value)
        })
    .disposed(by: bag)
  • Giờ chúng ta phát dữ liệu đi một cách lần lượt và xem nó hoạt động như thế nào.
    chu.onNext("Một")
    chu.onNext("Hai")
    so.onNext("1")
    so.onNext("2")
    
    chu.onNext("Ba")
    so.onNext("3")
    chu.onNext("Bốn")
    so.onNext("4")
    so.onNext("5")
    so.onNext("6")

Kết quả sẽ khác dự đoán của bạn một chút.

("Hai", "1")
("Hai", "2")
("Ba", "2")
("Ba", "3")
("Bốn", "3")
("Bốn", "4")
("Bốn", "5")
("Bốn", "6")

Kết quả là sự kết hợp dữ liệu từ 2 dữ liệu được Observable chữ và số phát đi. Bạn sẽ thấy là không có ("Một", "1"). Vì lúc đó Observable so chưa phát ra gì cả. Khi so phát ra phần tử đầu tiên thì sẽ kết hợp với phần tử mới nhất của chu, đó là Hai.

Áp dụng tương tự cho các phần tử tiếp theo. Còn với complete thì như thế nào?

    chu.onNext("Một")
    chu.onNext("Hai")
    so.onNext("1")
    so.onNext("2")
    
    chu.onNext("Ba")
    so.onNext("3")

    // completed
    chu.onCompleted()

    chu.onNext("Bốn")
    
    so.onNext("4")
    so.onNext("5")
    so.onNext("6")
    
    // completed
    so.onCompleted()

Kết quả thực thi như sau:

("Hai", "1")
("Hai", "2")
("Ba", "2")
("Ba", "3")
("Ba", "4")
("Ba", "5")
("Ba", "6")

Vẫn không ảnh hưởng gì tới sự hoạt động của toán tử này. Nó sẽ vẫn lấy dữ liệu cuối cùng trước khi phát đi .onCompleted để kết hợp với các phần tử khác.

3.2. combineLatest(_:_:resultSelector:)

Tiếp tục toán tự combineLatest trong nhóm toán tử Combining Operators. Kết quả thực thi ở trên nhìn khá là xấu xí. Tuy nhiên, bạn có thể biến đổi nó như các toán tử map bằng cách sử dụng thêm tham số resultSelector và cung cấp 1 closure để biến đổi chúng.

Ta edit lại ví dụ trên một chút.

    let observable = Observable.combineLatest(chu, so) { chu, so in
        "\(chu) : \(so)"
    }

Vì nếu không có tham số này, thì giá trị của toán tử là 1 Tuple kết hợp đơn giản mà thôi. Còn lại ta sử dụng tham số phụ này thì ta có quyền biến đổi thành kiểu dữ liệu mà ta mong muốn.

Kết quả như sau:

Hai : 1
Hai : 2
Ba : 2
Ba : 3
Ba : 4
Ba : 5
Ba : 6

Và đây là công thức chung cho bạn, nếu sau này muốn áp dụng nó. Bạn phải thêm filter để tăng tính đảm bảo.

let observable = Observable
		.combineLatest(left, right) { ($0, $1) }
    .filter { !$0.0.isEmpty }

Thêm 1 ví dụ nữa để thấy sự tiện lợi của toán tử này:

    let choice: Observable<DateFormatter.Style> = Observable.of(.short, .long)

    let dates = Observable.of(Date())

    let observable = Observable.combineLatest(choice, dates) { format, when -> String in
        let formatter = DateFormatter()
        formatter.dateStyle = format
        return formatter.string(from: when)
    }
    
    _ = observable.subscribe(onNext: { value in
        print(value)
    })

Với 1 giá trị Date bạn có thể lựa chọn kiểu format dữ liệu để in ra một cách tiện lợi nhất. Chúng ta không cần gọi hàm đi gọi hàm lại hay là for các kiểu nữa. Còn kết quả như sau:

8/21/20
August 21, 2020

Toán tử này có rất nhiều tuỳ chọn cho tham số của nó. Bạn hãy khám phá thêm.

3.3. zip

Nhóm toán tử Combining Operators này quá nhiều luôn. Chúng ta tiếp tục tìm hiểu về zip. Bạn hãy xem sơ đồ mô tả sau:

Khi bạn quan tâm tới thứ tự kết hợp theo đúng thứ tự phát đi của từng Observable. Nhưng combinedLatest không đáp ứng được thì zip sẽ giúp bạn hoàn thành tâm nguyện này.

Tất cả mọi thứ ví dụ đều như trên. Tuy nhiên, chỉ khác là các cặp giá trị kết hợp nhau thì sẽ theo thứ tự phát của các Observable. Xem qua lại ví dụ trên thì bạn sẽ hiểu thôi.

let observable = Observable.zip(chu, so) { chu, so in
        "\(chu) : \(so)"
    }

Vẫn là ví dụ lúc nãy, bạn chỉ cần edit lại thành là zip. Và tận hưởng kết quả nào!

Một : 1
Hai : 2
Ba : 3

Như vậy, là vừa đẹp vừa đúng rồi! Dù vậy, bạn cũng nên quản lý việc onCompleted của từng Observable trong đó, để đảm bảo dữ liệu như bạn mong muốn.

4. Trigger

Trigger sẽ được sử dụng, khi bạn muốn tạo ra 1 điều kiện nào đó từ Observable để một Observable khác được phép hoạt động.

4.1. withLatestFrom

Bắt đầu bằng ví dụ sau:

(Cái hình là mình mượn tạm để minh hoạ cho code ở đưới đây.)

  let button = PublishSubject<Void>()
  let textField = PublishSubject<String>()

  let observable = button.withLatestFrom(textField)
    
    _ = observable
        .subscribe(onNext: { value in
            print(value)
        })

    textField.onNext("Đa")
    textField.onNext("Đà Na")
    textField.onNext("Đà Nẵng")
    
    button.onNext(())
    button.onNext(())

Trong đó:

  • button là một subject. Với Void thì chỉ phát ra sự kiện, chứ không có giá trị nào từ onNext
  • textField là một subject, phát ra các String
  • observable là sự kết hợp của button với textField thông qua toán tử withLatestFrom
  • Mỗi lần button phát đi tín hiệu, thì kết quả sẽ nhận được là phần tử mới nhất từ textField

Qua ví dụ trên cũng mô tả cho bạn thấy sự hoạt động của toán tử withLatestFrom rồi. Kết quả thực thi code như sau:

Đà Nẵng
Đà Nẵng

4.2. sample

Chúng ta thay withLatestFrom bằng sample trong ví dụ trên.

let observable = textField.sample(button)

Kết quả sẽ cho ra 1 mà thôi.

Với sample là tương tự như withFromLatest. Nhưng nó chỉ phát khi Observable button phát ra.

Chú ý:

  • withLatestFrom thì tham số là dữ liệu của một Observable khác
  • sample thì tham số là trigger từ một Observable khác

Chúng nó rất dễ nhầm lẫn, vì vậy bạn cần cẩn thận hơn khi sử dụng.

5. Switches

Các toán tử mới từ Combining Operators này, sẽ cho phép bạn tạo ra một Observable từ nhiều Observable khác. Mà bạn có thể quyết định được việc dữ liệu từ nguồn nào để các subscriber có thể nhận được.

5.1. amb

Đây là một toán tử khá là mơ hồ, cũng như cái tên của nó là ambiguity. Với các đặc tính sau:

  • Nó sẽ tạo ra một Observable để giải quyết vấn đề quyết định nhận dữ liệu từ nguồn nào
  • Trong khi cả 2 nguồn đều có thể phát dữ liệu. Thì nguồn nào phát trước, thì nó sẽ nhận dữ liệu từ nguồn đó.
  • Nguồn phát sau sẽ bị âm thầm ngắt kết nối

Xem qua code demo cho thông não nè:

let bag = DisposeBag()

let chu = PublishSubject<String>()
let so = PublishSubject<String>()

let observable = chu.amb(so)

observable
    .subscribe(onNext: { (value) in
        print(value)
    })
.disposed(by: bag)

so.onNext("1")
so.onNext("2")
so.onNext("3")

chu.onNext("Một")
chu.onNext("Hai")
chu.onNext("Ba")

so.onNext("4")
so.onNext("5")
so.onNext("6")
   
chu.onNext("Bốn")
chu.onNext("Năm")
chu.onNext("Sáu")

Kết quả thực thi ra như sau:

1
2
3
4
5
6

Vì so đã phát trước, nên các dữ liệu từ chu sẽ không nhận được. Nếu bạn cho thêm chu phát onNext trước số thì sẽ thấy dữ liệu nhận được sẽ toàn là từ chu.

5.2. switchLatest

Toán tử này tương tự như flatMapLatest trong bài viết trước. Và để thấu hiểu nó, thì mình sẽ đi qua ví dụ từng bước sau.

Đầu tiên, bạn cần tạo ra các Observable.

let chu = PublishSubject<String>()
let so = PublishSubject<String>()
let dau = PublishSubject<String>()

let observable = PublishSubject<Observable<String>>()

Ta có:

  • 3 subject thay nhau phát dữ liệu
  • observable với kiểu dữ liệu phát đi là Obsevable<String> , chính là kiểu của 3 subject trên

Tiến hành subscribe và dùng switchLatest như sau:

observable
    .switchLatest()
    .subscribe(onNext: { (value) in
        print(value)
    }, onCompleted: {
        print("completed")
    })
.disposed(by: bag)

Cũng khá là quen thuộc phải không nào! Giờ sang phần phát dữ liệu đi. Bạn xem tiếp.

observable.onNext(so)

so.onNext("1")
so.onNext("2")
so.onNext("3")

observable.onNext(chu)

chu.onNext("Một")
chu.onNext("Hai")
chu.onNext("Ba")

so.onNext("4")
so.onNext("5")
so.onNext("6")

observable.onNext(dau)

dau.onNext("+")
dau.onNext("-")
   
observable.onNext(chu)
chu.onNext("Bốn")
chu.onNext("Năm")
chu.onNext("Sáu")

Bạn sẽ thấy việc observable sẽ phát đi subject nào. Thì subscriber trên sẽ nhận được giá trị của subject đó. Kết quả thực thi như sau:

1
2
3
Một
Hai
Ba
+
-
Bốn
Năm
Sáu

Đối với phần này rất dễ bị nhầm lẫn nên bạn muốn hiểu hơn, thì hãy thay phiên nhau việc phát dữ liệu.

Còn để kết thúc nó, thì phải phải .dispose subscription. Chứ không thể nào kết thúc nó được, mặc dù các subject có thể onCompleted hết tất cả nhưng nó vẫn không kết thúc.

6. Combining elements within a sequence

Tiếp theo là các toán tử của Combining Operators, với sự kết hợp các phần tử trong cùng 1 sequence observable. Có nhiều điểm thú vị với các toán tử này.

6.1. reduce

Đây là một toán tử khá là quen thuộc trong Swift code. Chắc bạn cũng vài lần sử dụng nó trong các Array để tính toán liên quan tới tất cả các phần tử trong array đó.

Ví dụ như cộng tất cả giá trị của một array lại với nhau. Hình sau đây cũng minh hoạ cho ví dụ này.

Về ví dụ bằng code thì như sau:

let source = Observable.of(1, 2, 3, 4, 5, 6, 7, 8, 9)

let observable = source.reduce(0, accumulator: +)

_ = observable
    .subscribe(onNext: { value in
        print(value)
    })

Trong đó accumulator là sự rút gọn toán tử + lại. Và 0 là giá trị ban đầu được cấp phát cho để thực hiện việc này.

Hoặc bạn có thể code xịn sò hơn như sau:

let observable = source.reduce(0) { $0 + $1 }

Hoặc code nghiêm chỉnh lại một chút.

let observable = source.reduce(0) { summary, newValue in
  return summary + newValue
}

Việc tích luỹ sẽ bắt đầu bằng giá trị bạn cung cấp cho nó. Khi đó nó sẽ hiểu là $0. Tiếp theo khi nhận được 1 giá trị, thì giá trị đó là $1. Ta thực hiện biểu thức, kết quả trả về sẽ gán lại cho $0. Cứ như thế, vòng lặp định mệnh sẽ liếp tục cho đến hết. Tức là Observable phát đi giá trị cuối cùng được tính toán xong sau khi phát onCompleted.

OKAY phải không nào, EZ.

6.2. scan(_:accumulator:)

Thêm một thành viên hack não nữa từ nhóm toán tử Combining Operators. Bạn xem qua sơ đồ mô tả sau:

Về cấu trúc và cách viết thì tương tự reduce. Có chút khác biệt ở đây là, thay vì chờ Observable kết thúc và đưa ra kết quả cuối cùng. Thì scan nó sẽ tính toán và phát đi từng kết quả  tinh toán được, sau khi có dữ liệu từ Observable phát ra. Không quan tâm Observable kết thúc mới thực hiện.

Chỉ cần dùng lại ví dụ trên, thay reduce bằng scan là bạn sẽ hiểu thôi.

let source = Observable.of(1, 2, 3, 4, 5, 6, 7, 8, 9)

//let observable = source.scan(0, accumulator: +)

//let observable = source.scan(0) { $0 + $1 }

let observable = source.scan(0) { summary, newValue in
  return summary + newValue
}

_ = observable
    .subscribe(onNext: { value in
        print(value)
    })

Kết quả thực thi như sau:

1
3
6
10
15
21
28
36
45

Về bản chất thì không khác nhau mấy khi so với reduce. Về ý nghĩa thì bạn sẽ có 1 cách tạo ra 1 for loop xịn sò nữa. Ahihi!

Mình xin hết thúc bài viết về nhóm toán tử Combining Operators tại đây. Nếu có gì thắc mắc hay góp ý cho mình thì bạn có thể để lại bình luận hoặc gởi email theo trang Contact. Hẹn gặp lại bạn ở các phần tiếp theo của các nhóm toán tử trong RxSwift.

Tạm kết

Mình sẽ tóm tắt lại ý nghĩa các toán tử trong nhóm Combining Operators nha.

  • startWith để thêm một hoặc nhiều phần tử trước khi Observable phát ra giá trị đầu tiên.
  • concat dùng để nối nhiều Observables lại với nhau. Hoặc tiếp tục việc phát dữ liệu sau khi một Observable kết thúc bằng 1 Observable khác.
  • concatMap vừa nối vừa biến đổi
  • merge hợp nhất các giá trị từ nhiều Observables phát ra (không theo thứ tự) thành 1 Observable duy nhất.
  • combineLatest kết hợp các cặp giá trị mới nhất từ các Observables. Và không quan tâm tới thứ tự phát.
  • zip tương tự như combineLatest nhưng cặp giá trị kết hợp sẽ theo thứ tự phát của các Observables.
  • withLatestFromlà trigger với tham số là dữ liệu của một Observable khác. Nó phát và nhận giá trị từ người khác.
  • sample cũng là trigger, nhưng tham số là một Observable khác. Khi người khác phát thì nó sẽ phát ra dữ liệu.
  • amb giải quyết việc chọn Observables nào sẽ toàn quyền phát dữ liệu. Bằng cách xem Observable nào phát trước tiên, các Observable còn lại thì sẽ bị ngắt kết nối.
  • switchLatest thì chỉ nhận dữ liệu phát ra từ Observable cuối cùng tham gia vào.
  • reduce làm gọn lại tất cả các dữ liệu phát ra từ Observable bằng một luật tính toán nào đó. Khi Observable kết thúc thì sẽ nhận được kết quả. Ngoài ra, subscriber sẽ không nhận được bất kì giá trị nào khác.
  • scan tương tự như reduce. Nhưng subscriber sẽ nhận được kết quả ở từng bước tính toán khi Observable phát dữ liệu đi.

Cảm ơn bạn đã đọc bài viết này!

FacebookTweetPinYummlyLinkedInPrintEmailShares20

Related Posts:

  • RxSwift - Filtering Operators
    RxSwift - Filtering Operators
  • RxSwift vs. UIKit - Hello ViewController
    RxSwift vs. UIKit - Hello ViewController
  • RxSwift - Hello Subjects
    RxSwift - Hello Subjects
  • RxSwift - Transforming Operators
    RxSwift - Transforming Operators
Tags: rxswift
Written by chuotfx

Hãy ngồi xuống, uống miếng bánh và ăn miếng trà. Chúng ta cùng nhau đàm đạo về đời, về code nhóe!

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Donate – Buy me a coffee!

Fan page

Fx Studio

Tags

Actor Advanced Swift api AppDistribution Asynchronous autolayout basic ios tutorial blog callback ci/cd closure collectionview combine concurrency CoreData Core Location crashlytics darkmode dart dart basic dart tour Declarative decoding delegate deploy fabric fastlane firebase flavor flutter GCD iOS mapview MVVM optional protocol rxswift Swift Swift 5.5 SwiftUI SwiftUI Notes tableview testing TravisCI unittest

Recent Posts

  • Raw String trong 10 phút
  • Dispatch Semaphore trong 10 phút
  • Tổng kết năm 2022
  • KeyPath trong 10 phút – Swift
  • Make color App Flutter
  • Ứng dụng Flutter đầu tiên
  • Cài đặt Flutter SDK & Hello world
  • Coding Conventions – người hùng hay kẻ tội đồ?
  • Giới thiệu về Flutter
  • Tìm hiểu về ngôn ngữ lập trình Dart

You may also like:

  • RxSwift vs. UIKit – Tương tác giữa các ViewController
    RxSwift vs. UIKit – Tương tác giữa các ViewController
  • RxSwift - Publish Subjects
    RxSwift - Publish Subjects
  • RxSwift - Creating an Observable
    RxSwift - Creating an Observable
  • RxSwift - Traits
    RxSwift - Traits
  • RxSwift - Hello Subjects
    RxSwift - Hello Subjects

Archives

  • February 2023 (1)
  • January 2023 (2)
  • November 2022 (2)
  • October 2022 (1)
  • September 2022 (5)
  • August 2022 (6)
  • July 2022 (7)
  • June 2022 (8)
  • May 2022 (5)
  • April 2022 (1)
  • March 2022 (3)
  • February 2022 (5)
  • January 2022 (4)
  • December 2021 (6)
  • November 2021 (8)
  • October 2021 (8)
  • September 2021 (8)
  • August 2021 (8)
  • July 2021 (9)
  • June 2021 (8)
  • May 2021 (7)
  • April 2021 (11)
  • March 2021 (12)
  • February 2021 (3)
  • January 2021 (3)
  • December 2020 (3)
  • November 2020 (9)
  • October 2020 (7)
  • September 2020 (17)
  • August 2020 (1)
  • July 2020 (3)
  • June 2020 (1)
  • May 2020 (2)
  • April 2020 (3)
  • March 2020 (20)
  • February 2020 (5)
  • January 2020 (2)
  • December 2019 (12)
  • November 2019 (12)
  • October 2019 (19)
  • September 2019 (17)
  • August 2019 (10)

About me

Education, Mini Game, Digital Art & Life of coders
Contacts:
contacts@fxstudio.dev

Fx Studio

  • Home
  • About me
  • Contact us
  • Mail
  • Privacy Policy
  • Donate
  • Sitemap

Categories

  • Art (1)
  • Blog (22)
  • Code (4)
  • Combine (22)
  • Flutter & Dart (24)
  • iOS & Swift (86)
  • RxSwift (37)
  • SwiftUI (76)
  • Tutorials (70)

Newsletter

Stay up to date with our latest news and posts.
Loading

    Copyright © 2023 Fx Studio - All rights reserved.

    Share this ArticleLike this article? Email it to a friend!

    Email sent!