Найкраща стратегія звітування про прогрес в інтерфейсі - як має відбуватися зворотний виклик?


11

Іноді користувач запускає розширену технічну операцію, яка потребує певного часу. У цих випадках зазвичай приємно відображати якусь панель прогресу, а також інформацію про те, яке завдання виконується зараз.

Щоб уникнути тісного з’єднання інтерфейсу користувача та логічних шарів, зазвичай, краще, щоб спілкування відбувалося через якийсь проксі. Тобто, бек-енд не повинен маніпулювати власними елементами інтерфейсу або навіть безпосередньо взаємодіяти з посередницьким шаром.

Очевидно, що для того, щоб зробити цю роботу, десь повинен бути якийсь зворотний дзвінок. Я зазвичай реалізував це одним із двох способів:

  1. Передайте змінений об’єкт до бек-енду і змушуйте його вносити зміни в хід. Об'єкт повідомляє лицьову сторону, коли відбувається зміна.

  2. Передайте функцію зворотного дзвінка форми void f(ProgressObject)або ProgressObject -> unitте, що викликає зворотній зв'язок. У цьому випадку бек-енд сконструює ProgressObjectі це повністю пасивно. Я повинен будувати новий об'єкт кожного разу, коли він хоче повідомити про прогрес.

Які недоліки та переваги цих методів? Чи є узгоджений найкращий метод використання? Чи існують різні обставини їх використання?

Чи існують зовсім інші методи звітування про прогрес, які я не помітив?


1
Щодо змінних та незмінних, переваги та недоліки такі ж, як і деінде. Щодо об’єкта прогресу, це може бути дуже легким; це може бути так само просто, як і одне число: відсоток.
Роберт Харві

@RobertHarvey Розмір об'єкта прогресу зазвичай залежить від вимог інтерфейсу. Подивіться, наприклад, діалогове вікно копіювання Windows. Я думаю, це вимагає багато інформації.
GregRos

1
@RobertHarvey Це новина для мене. Що це?
GregRos

1
Я кусаю. Ми використовуємо BackgroundWorkerце RH згадує. Загорнутий у нестандартний клас разом із "формою прогресу" тощо та простим механізмом передачі винятку - як BackgroundWorkerза допомогою дизайну працює в окрему нитку. Наскільки ми використовуємо його риси у спосіб, запропонований .Net, тоді це можна сказати як ідіоматичне. І в будь-якому даному мовному / рамковому контексті "ідіоматичне" може бути найкращим.
radarbob

2
Я не бачу суттєвих відмінностей між вашими двома методами. Об'єкт, переданий від переднього кінця до бекенда, який пропонує методи, що призводять до повідомлення про передній кінець, фактично має функцію зворотного виклику. І якщо ваш другий підхід використовує більш-менш складний об'єкт параметрів для передачі інформації, або якщо він використовує кілька простих значень, це не має значення з архітектурної точки зору. В обох підходах бекенд активно інформує інтерфейс, відмінності - це лише незначні деталі, тому іншої концепції тут не описано.
Док Браун

Відповіді:


8

Передайте змінений об’єкт до бек-енду і змушуйте його вносити зміни в хід. Об'єкт повідомляє лицьову сторону, коли відбувається зміна.

Важко збалансувати ефективність, якщо сервіс сповістив про це з цього приводу. Без уваги ви можете виявити, що збільшення вашого прогресу закінчується подвоєнням або скороченням утроє часу, необхідного для завершення операції, якщо ви прагнете до дуже плавного оновлення прогресу.

Передайте функцію зворотного виклику форми void f (ProgressObject) або ProgressObject -> одиниці, до якої викликається бек-енд. У цьому випадку бек-енд сконструює ProgressObject і він повністю пасивний. Я повинен будувати новий об'єкт кожного разу, коли він хоче повідомити про прогрес.

Я не розумію різниці тут.

Чи існують зовсім інші методи звітування про прогрес, які я не помітив?

Опитуйте з переднього кінця в окремому потоці з атомними приростами в резервному. Опитування має сенс тут, оскільки це стосується операції, яка закінчується протягом обмеженого періоду, і ймовірність того, що фронтенд підбере зміни стану, високий, особливо якщо ви прагнете до шовковистої плавної смуги прогресу. Ви можете розглянути змінні умови, якщо вам не подобається ідея опитування з фронтальної нитки, але в такому випадку ви можете уникати повідомлень про кожен окремий приріст панелі прогресу.


2

Це різниця між механізмом сповіщення " push and pull" .

Об'єкт, що змінюється ( витяг ), повинен бути повторно опитаний користувальницьким інтерфейсом та синхронізований, якщо ви очікуєте, що завдання заднього кінця буде виконано у фоновому / робочому потоці.

Зворотний виклик ( поштовх ) створить роботу для інтерфейсу користувача лише тоді, коли щось насправді зміниться. У багатьох фреймворках інтерфейсу також є виклик invokeOnUIThread з робочої нитки, щоб зробити фрагмент коду запущеним на потоці користувальницького інтерфейсу, щоб ви могли фактично вносити зміни, не ступаючи до небезпек, пов'язаних з потоками. (каламбур призначений)

Загалом, натискання сповіщень є кращими, оскільки вони працюють лише тоді, коли роботу потрібно виконати.


1
Я думаю, що те, що ти кажеш, взагалі вірно. Однак для цього конкретного випадку, смуга прогресу, зміни можуть відбуватися швидко. Якщо ви очікуєте, що "прогрес", ймовірно, змінюватиметься багато разів на секунду, має сенс використовувати модель "тягнення", оскільки в іншому випадку вам доведеться турбуватися про те, що інтерфейс отримує занадто багато сповіщень.
Gort the Robot

Надсилання об'єкта прогресу може затьмарити механізм сповіщень, який ви використовуєте з бек-енду, оскільки, можливо, об'єкт прогресу виконує зворотні дзвінки. Насправді я ніколи не використовував механізм витягування, наскільки я пам’ятаю, і я про це забув: P
GregRos

The mutable object (the pull) will need to be repeatably polled by the UI and synchronized if you expect the back-end task to be executed in a background/worker thread.- Не, якщо об'єктом, що змінюється, є сам діалог або робочий інтерфейс до нього. Звичайно, це все одно становить зворотний виклик.
Роберт Харві

1
Так? ОП чітко описує дві різні форми механізму натискання, в жодній не потрібне опитування.
Док Браун

0

Я використовую веб-розетки з AngularJS. Коли передній кінець отримує повідомлення, він відображає його у визначеній області повідомлень, яка через декілька секунд затухає. На зворотному кінці я просто розміщую повідомлення про стан у черзі повідомлень. Я надсилаю лише текст, але немає причин, щоб я не міг надіслати об'єкт статусу зі значеннями, такими як відсоток завершеності або швидкість передачі.


0

Ви згадуєте свої "два способи", ніби це окремі поняття, але я хочу трохи відштовхнутися від цього.

  1. Передайте змінений об’єкт до бек-енду і змушуйте його вносити зміни в хід. Об'єкт повідомляє лицьову сторону, коли відбувається зміна.

Ви вже говорили, що ви хочете уникнути тісного з’єднання інтерфейсу користувача та логіки, тому я можу сміливо припустити, що цей "змінний об'єкт", який ви передаєте, насправді є реалізацією певного інтерфейсу, який визначений у логічному модулі. Таким чином, це лише інший спосіб передачі зворотного дзвінка в процес, який періодично дзвонить з інформацією про прогрес.

Що стосується переваг та недоліків ...

Недолік методу (1) полягає в тому, що клас, який реалізує інтерфейс, може зробити це лише один раз. (Якщо ви хочете виконувати різні завдання з різними викликами, вам знадобиться оператор перемикання або шаблон відвідувача.) За допомогою методу (2) той самий об'єкт може використовувати інший зворотний виклик для кожного виклику резервного коду без необхідності перемикач.

Міцність методу (1) полягає в тому, що набагато простіше мати кілька методів в інтерфейсі, ніж мати справу з декількома зворотними зворотами викликів методу (2) або одним зворотним викликом з оператором перемикання для кількох контекстів.


-2

Методи, які ви можете використовувати, можуть бути дуже різними.

Я намагаюся розібратися з різним сценарієм

  • Запит на дб
  • завантажити файл

Простий запит на вхід до db (середня відповідь від db одним елемтом) не потребує прогресу звіту, але він завжди може запустити потік інтерфейсу користувача в окремому завданні, наприклад. async або backgroundworker, тут вам потрібен лише один зворотний дзвінок для результату.

Але що робити, якщо ви запитаєте, щоб побачити весь свій інвентар з предметом 1млн? Цей запит повинен зайняти кілька хвилин для завершення, тож у цьому випадку вам потрібно впровадити свій прогрес у виконанні вашої бізнес-логіки у формі / елементах форми, тоді ви можете оновити інтерфейс користувача і, можливо, надати можливість скасувати зворотний виклик.

Той самий випадок для завантаження файлу. Ви завжди можете реалізувати тут свій зворотний виклик прогресу у формі байтів байтів, і утримувати весь контроль комунікації над http дуже часто.

При особистому підході я застосовую свою логіку прогресу бізнесу лише своїм клієнтам, уникаючи спільного використання інших об'єктів з кінцевою точкою.


1
Це насправді не відповідає на питання про переваги / недоліки.
Бенні
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.