Schedulers in Swift Combine Framework

by TienVV8
139 views

iOS 13 Apple đã giới thiệu đến các developer một big framework, có tên là Combine. Framework này cung cấp rất nhiều thứ thú vị, trong đó có Schedulers. Trong bài này mình sẽ giới thiệu đến các bạn Schedulers.

Nội dung:

  • Scheduler trong Combine là gì?
  • Các kiểu của Scheduler trong combine.
  • Làm thế nào để switch schedulers?
  • Làm thế nào để perform asynchronous với Combine?
  • Sự khác nhau giữa receive(on:) và subscribe(on:)?

Scheduler là gì?

Scheduler Là cơ chế đồng bộ hoá của framework Combine. Nó xác định Context là gì, thực hiện công việc ở đâu (where), thực hiện công việc khi nào (when)

  • Where: Có nghĩa là Run loop hiện tại, dispatch queue hoặc operation queue.
  • When: Có nghĩa là thời gian ảo, tính theo thời gian của Scheduler, công việc được thực hiện bởi Scheduler phải tuân thủ theo thời gian của Scheduler, có thể không tương ứng với thời gian thực tế của hệ thống.

Các kiểu của Scheduler trong combine

Framework Combine cung cấp nhiều kiểu của Schedule khác nhau:

  • DispatchQueue: Thực hiện công việc trên một dispatch queue cụ thể: serial, concurrent, main and global. Thông thường serial, global dùng cho các công việc dưới background, và main queue sử dụng cho việc update UI. từ Xcode 11 GM Seed thì concurrent queues không được khuyến khích sử dụng.
  • OperationQueue: Tương tự như DispatchQueue, sử dụng OperationQueue.main cho các công việc liên quan đến UI, và các queue khác sử dụng cho công việc background. Theo như bài này trên một diễn đàn về Swift thì không khuyến khích sử dụng operationQueue với maxConcurrentOperations lớn hơn 1.
  • RunLoop: Thực hiện công việc trên một RunLoop cụ thể
  • ImmediateScheduler: Thực hiện các hành động đồng bộ ngay lập tức. App sẽ terminate với một fatalError nếu bạn cố gắng thực hiện delay task.

Sử dụng RunLoop.main, DispatchQueue.main hoặc OperationQueue.main để thực hiện công việc liên quan UI. Không có sự khác biệt giữa chúng.

Scheduler Mặc định

Ngay cả khi bạn không chỉ định bất kì scheduler nào, Combine vẫn cung cấp cho bạn một scheduler mặc định, scheduler này sử dụng cùng thead với nơi nó được tạo ra. Ví dụ: nếu bạn bắn một sự kiện nào đó từ background thread thì bạn sẽ nhận được sự kiện đó cùng thread với nơi scheduler được tạo ra là background thread

  1. In ra true nếu nhận được sự kiện ở main thread và false nếu ở thead khác
  2. gửi một sự kiện đi từ main thread
  3. gửi một sự kiện từ global

Và kết quả in ra ở đây lần lượt là true false. Đồng nghĩa là scheduler ở nơi nhận sự kiện giống với scheduler ở nơi sự kiện được sinh ra.

Switching Schedulers

Thông thường các hoạt như call API được xử lý ở background thread để UI không bị block. Sau khi call API thì thường update lại UI và công việc này được thực hiện trên main thread. Cách thức của Combine để thực hiện việc này là schitch schedulers. Nó được thực hiện với sự trợ giúp của hai methods: subscribe(on:) và receive(on:).

  • receive(on:) Method này thay scheduler của tất cả những operators sau nó

    Và đây là kết quả:

    Chúng ta có thể thấy map và sink đứng sau receive và đã thay đổi scheduler bởi receive.

    * Vị trí của receive là rất quan trọng bởi vì nó chỉ làm thay đổi scheduler của những operators đứng sau nó
  • subscribe(on:) Method này thay đổi scheduler của subscribe, cancel, and request operations.

    và đây là kết quả

    Nhìn khá giống với receive nhỉ? Cùng nhau đi đến một ví dụ nữa nhé. Cụ thể bây giờ chúng ta chuyển subscribe xuống một dong

    Lúc này kết quả in ra vẫn là false false

    * Vị trí của subscribe là không quan trọng, chỉ đơn giản là đăng ký event đó ở thread nào thôi.

Thực hiện Asynchronous với Combine

Trong thực tế khi lập trình chúng ta thường kết hơp hai methods subscribe(on:) and receive(on:). Cùng đi vào ví dụ cụ thể nhé!

Ví dụ mình có một công việc cần thời gian dài để hoàn thành

Khi call với main thread nó sẽ làm UI bị block trong 10s. Hãy nhớ rằng schuduler mặc định sẽ chạy cùng thread ở nơi nó được sinh ra

Với lần call này thì ‘hello’ sẽ được in ra sau, cụ thể là đợi in ra ‘Received value’ sau đó mới thực hiện in ‘hello’. Block UI như thế này thực sự không cho phép trong lập trình. Cùng đi tiếp để xem hướng giải quyết vấn đề này trong trong Combile nhé!

Pattern phổ biến để thực hiện asynchronous trong Combile là thực hiện subscribe ở background thread và recive ở main thread

với lần call này thì ‘hello’ đã được in ra trước. Tuyệt vời! bài toán block UI đã được giải quyết.

Bài viết này mình đã giới thiếu đến các bạn Scheduler, một phần trong Combile được Apple giới thiệu ở iOS 13

Mình hi vọng bài viết có thể giúp ích được cho các bạn. Chúc các bạn thành công!

Leave a Comment

* By using this form you agree with the storage and handling of your data by this website.