เริ่มต้น Reactive Programming ด้วย Combine Part5: Combining Operator
Combine มี operators หลายตัวที่ใช้ในการผสานข้อมูลจาก publishers ต่างๆ และแต่ละตัวมีวัตถุประสงค์เฉพาะของตัวเอง ในบทนี้เราจะมาสำรวจว่าแต่ละตัวทำงานยังไงบ้างและเราสามารถหยิบเอามาใช้ให้เหมาะสมกับงาน
combineLatest
คือการรวมค่าสุดท้ายของ publishers มากกว่า 2 ตัวขึ้นไป และไม่จำเป็นต้องเป็น type เดียวกันก็ได้ จะทำงานก็ต่อเมื่อ publishers ตัวใดตัวหนึ่ง มี Event ใหม่เข้ามาและใช้ค่าล่าสุดของแต่ publishers มาคำนวณ
func combineLatest<P, T>(
_ other: P,
_ transform: @escaping (Self.Output, P.Output) -> T
) -> Publishers.Map<Publishers.CombineLatest<Self, P>, T> where P : Publisher, Self.Failure == P.Failure
example
let pub1 = PassthroughSubject<Int, Never>()
let pub2 = PassthroughSubject<Int, Never>()
cancellable = pub1
.combineLatest(pub2) { (v1, v2) in
return v1 * v2
}
.sink { print("Result: \($0).") }
pub1.send(1)
pub1.send(2)
pub2.send(2)
pub1.send(9)
pub1.send(3)
pub2.send(12)
pub1.send(13)
//
// Prints:
//Result: 4. (pub1 latest = 2, pub2 latest = 2)
//Result: 18. (pub1 latest = 9, pub2 latest = 2)
//Result: 6. (pub1 latest = 3, pub2 latest = 2)
//Result: 36. (pub1 latest = 3, pub2 latest = 12)
//Result: 156. (pub1 latest = 13, pub2 latest = 12)
combineLatest อธิบายโดยใช้ marble diagram อธิบายได้ดังนี้
pub1: |----1----2--------9----3---------11-------------------|-->
pub2: |-------------2--------------12------------------------|-->
opratoion: pub1.combineLatest.pub2 { v1 * v2 }
newPub: |--------------4---18----6----36--156------------------|-->
time(s):|----|----|----|----|----|----|----|----|----|----|----|-->
0 1 2 3 4 5 6 7 8 9 10 11
append
คือการเอา publishers ที่มีการสิ้นสุดการทำงานแล้วหรือสามารถเกิด event ได้อีก มาต่อกัน เช่น a.append(b)
func append(_ elements: Self.Output...) -> Publishers.Concatenate<Self, Publishers.Sequence<[Self.Output], Self.Failure>>
example
let numbers1 = (1...5).publisher
let numbers2 = (6...10).publisher
let numbers3 = numbers1.append(numbers2)
numbers3.sink {
print($0) // 1,2,3,4,5,6,7,8,9,10z
}
numbers1: |--12345--|------------------->
numbers2: |--5678910-|------------------>
opratoion: numbers1.append(numbers2)
numbers3: |--------------12345678910------------------|-->
time(s):|----|----|----|----|----|----|----|----|----|----|----|-->
0 1 2 3 4 5 6 7 8 9 10 11
merge
คือการรวม publishers มากกว่า 1 ตัวเข้ามาเป็น publishers ตัวเดียวกัน
func merge<B, C>(
with b: B,
_ c: C
) -> Publishers.Merge3<Self, B, C> where B : Publisher, C : Publisher, Self.Failure == B.Failure, Self.Output == B.Output, B.Failure == C.Failure, B.Output == C.Output
exmaple
let pubA = PassthroughSubject<Int, Never>()
let pubB = PassthroughSubject<Int, Never>()
let pubC = PassthroughSubject<Int, Never>()
let newPub = pubA.merge(with: pubB, pubC)
let cancellable = newPub.sink { print("\($0)", terminator: "," )}
pubA.send(1)
pubB.send(40)
pubC.send(90)
pubA.send(2)
pubB.send(50)
pubC.send(4)
// Output: 1,40,90,2,50,4,
pubA: |----1-------------2-----------------------------------|-->
pubB: |--------40-------------50-----------------------------|-->
pubC: |-------------90-------------4-------------------------|-->
opratoion: pubA.merge(with: pubB, pubC)
newPub: |----1---40----90---2---50----4------------------------|-->
time(s):|----|----|----|----|----|----|----|----|----|----|----|-->
0 1 2 3 4 5 6 7 8 9 10 11
zip
คือการรวม publishers โดยจับคู่ value ในลำดับที่เท่ากัน อาจจะมองไม่เห็นภาพดูตัวอย่างกันดีกว่า
func zip<P>(_ other: P) -> Publishers.Zip<Self, P> where P : Publisher, Self.Failure == P.Failure
example
let numbersPub = PassthroughSubject<Int, Never>()
let lettersPub = PassthroughSubject<String, Never>()
let zipPub = numbersPub.zip(lettersPub)
let cancellable = zipPub.sink { print("\($0)") }
numbersPub.send(1) // numbersPub: 1 lettersPub: zip output: <none>
numbersPub.send(2) // numbersPub: 1,2 lettersPub: zip output: <none>
lettersPub.send("A")// numbers: 1,2 letters:"A" zip output: <none>
numbersPub.send(3) // numbers: 1,2,3 letters: zip output: (1,"A")
lettersPub.send("B")// numbers: 1,2,3 letters: "B" zip output: (2,"B")
// Prints:
// (1, "A")
// (2, "B")
numbersPub: |----1----2---------3----------------------------------|-->
lettersPub: |--------------A---------B-----------------------------|-->
opratoion: numbersPub.zip(lettersPub)
zipPub: |------------(1,A)-----(2,B)---------------------------|-->
time(s): |----|----|----|----|----|----|----|----|----|----|----|-->
0 1 2 3 4 5 6 7 8 9 10 11
บทความนี้เป็นการยกตัวอย่าง Combining Operator ที่สำคัญๆ 4 ตัว แต่จริงๆแล้วมันมีมากกว่านี้ สามารถเข้าไปอ่านได้ที่ developer.apple.com หรือลิ้งด่านล้างนี้ครับ
Next part6: Reactive Programming ด้วย Combine Part6: Filtering Operator