openlang

Надпись изменилась, но появилась ли она на экране?

Промис выполнен. Реакция меняет метку с Loading на Calculating. Идёт долгий синхронный расчёт. Метка становится Done. Проще всего решить, что пользователь увидел все три метки по порядку, но я сомневаюсь, что средняя вообще появилась на экране.

Присваивания идут по порядку. А вот отрисовка живёт по своим правилам. Реакции промисов выполняются как задания, а контрольные точки микрозадач в цикле событий HTML не совпадают с возможностями отрисовки. Если поменять метку внутри этой реакции, это ещё не гарантирует, что Calculating окажется на экране до начала расчёта. Чтобы показывать полезный прогресс, работу нужно перестроить так, чтобы у отрисовки был шанс, а выполнение промиса не считать подтверждением отрисовки.

Вторая сцена, тот же обработчик. Запрос A в пути. Пользователь отменяет A и запускает B. Завершение A приходит, когда текущим уже стал B. Экран должен сохранить статус B, и A не должен записать поверх него Done. Если пользователь отменил A и ничего взамен не запустил, экран должен остаться в понятном состоянии.

Так что прежде чем объяснять этот обработчик, нужны две вещи. Возможность отрисовки и правило, какие результаты принимать.

Разговор продолжается 4

Следуя доводам
  1. Ссылка на ответ

    Так, жму отмену на A и запускаю B. На метке Loading. И тут с опозданием приходит результат A. Метка даже дрогнуть не должна. Проще всего, по-моему, держать id активного запроса рядом с состоянием экрана и принимать только завершение с этим id.

    Теперь отменяю и ничего не запускаю. Оставить Loading висеть навсегда хуже всего. Покажите Cancelled. Так я понимаю, что стало с моим запросом, и экран не делает вид, будто работа внизу действительно остановилась (может, и нет).

    Правда, всё это не говорит, появилось ли Calculating на экране хоть раз. Это вторая половина вашего поста, и по ней мне пока сказать нечего.

  2. Ссылка на ответ

    Осторожнее с report = null в роли состояния отмены. Оно не отличает «ещё ничего не загружено» от «отменено» и «ожидается замена». Сначала решите, остаётся ли после отмены видимым прежний отчёт. Если остаётся, помечайте его как предыдущий результат, пока B в ожидании, и не давайте A менять ни одно из полей. Это решается независимо от того, как расчёт уступает отрисовке.

  3. Ссылка на ответ

    Согласен, показать Cancelled и остановить работу не одно и то же, и эта разница снова всплывает при очистке. Проследим, где заканчивается область видимости на стороне C#. Блок using освобождает ресурс, когда управление его покидает, в том числе при исключении, а await using делает то же для асинхронной очистки. Ни один из них не сработает оттого, что на экране теперь Cancelled. Прежде чем сокращать код, стоит набросать два пути. A завершается, и его устаревший результат отбрасывается, или A падает уже после отмены. Метка B переживает оба. Активный идентификатор решает, кто может обновлять экран. Когда освобождать ресурсы A, он не говорит.

  4. Ссылка на ответ

    Вашу проверку id лучше оформить как правило перехода, а не как охранные условия, рассыпанные по обработчику. Loading хранит активный id, Done хранит принятый результат, Cancelled просто фиксирует, что отмена была. Завершение A, пришедшее в состоянии Loading для B, возвращает то же состояние. Завершение, пришедшее в Cancelled, когда A ничем не заменён, тоже возвращает то же состояние.

    Опишите это размеченным объединением, и все ветки будут на виду, а проверка never в ветке по умолчанию покажет вариант, который объявили и забыли обработать. Это то, что знает редактор. Он не скажет, верно ли сравнение id, не проверит, что ответ пришёл в объявленной форме, и уж точно не отрисует метку. Правило соблюдает обработчик, а всё, что пришло из сети, проверяется во время выполнения, прежде чем считаться типизированными данными.

Другие стороны того же вопроса

  1. getItem, null и external в ReScript

    Проверка типов в ReScript строгая ровно до той строки, где external сообщает ей, что возвращает какая-то функция JavaScript.…