Больше никаких (╯ ° □ °) ╯︵ ┻━┻, потому что теперь у вас есть Async Manager

Насколько раздражает, когда вы нажимаете «Сохранить», а потом ничего не происходит? Вы разработчик, поэтому вы открываете консоль браузера и проверяете, нет ли ошибок… ничего. Итак, ждите и смотрите вкладку «Сеть». В конце концов, вы видите разрешение вызова Ajax и, конечно же, видите сообщение в пользовательском интерфейсе, что ваше сохранение было успешным. Это не сделает вас менее разочарованным, и это не сделает ваше кровяное давление резким :) ха-ха. Я, конечно, немного шучу, но это определенно разочаровывает пользователей, когда это происходит.

Удобнее для пользователя, когда вы видите, что «Сохранить» превратилось в «Сохранение…». На самом деле это происходит, когда я печатаю, но немного по-другому. В Medium, когда вы пишете рассказ, время от времени вы видите что-то в верхней части страницы с надписью «Сохранение…», затем оно переключается на «Сохранено» и затем исчезает. Это контекстная маркировка, которая дает гораздо лучший опыт, чем оставлять пользователя в неведении относительно того, что происходит.

Да, это может показаться очевидным, но есть причины, по которым приложения иногда этого не делают. Одним из недостатков является то, что каждый элемент пользовательского интерфейса имеет свои собственные API-интерфейсы, которые он использует. Да, у вас, вероятно, есть общие компоненты, поэтому вы везде используете одну и ту же кнопку ... но это не один и тот же API. В одном месте вы сохраняете результаты поиска, а в другом получаете изображение (в качестве примеров). Они общаются с разными API. Итак, если вы хотите, чтобы такое поведение было повсюду, вы должны добавить его в компонент-оболочку везде. Или ты? …

Очевидно, я бы не писал этого, если бы у меня не было ответа на этот вопрос. Нет, вам не нужно касаться каждого компонента, написав компонент-оболочку. Вы можете справиться со всем, создав центральное место, где можно управлять всем. Я называю это Async Manager, и это довольно просто, но при этом невероятно полезно (лучший вид кода).

В первую очередь, как всегда, я говорю о приложениях, использующих React + Redux. Кроме того, в моем примере я буду ссылаться на ImmutableJS, но это действительно необязательно. React + Redux - вот что заставляет все это работать. Хорошо, админка готова :)

Async Manager - это простая система: это список асинхронных идентификаторов. Когда происходит асинхронный вызов, в список добавляется идентификатор. Когда вызов разрешается, идентификатор удаляется из списка.

Редуктор довольно прост, и на самом деле ему нужно только прослушивать «начало» и «конец» действия. Вот фрагмент кода:

Для Action Creators файл также на удивление прост:

Понимаете, что я имею в виду? Все очень просто. Вы просто ведете список идентификаторов. Когда запускается асинхронный вызов, добавьте идентификатор. Когда он разрешится, удалите его.

Затем вы должны намеренно подключить его к местам в вашем приложении. Для нас я добавил его в нашу центральную логику Ajax. У нас есть модуль, который делает все за нас, включая обработку ошибок. В этом модуле было просто добавить использование begin и использование end в нужных местах. В частности, добавьте начало там, где происходит вызов, и конец, где он разрешается успешным обратным вызовом И, где он разрешается с ошибкой.

Теперь у вас есть довольно простая задача: определить ваши основные компоненты (по крайней мере, на начальном этапе), которые вы хотите использовать в своих интересах этой архитектуры. Дайте этим компонентам возможность использовать Async ID. Для нас первым и главным местом был компонент Button. Мы используем константы во всем приложении и организуем их по-своему. Итак, мы добавили файл для управления всеми константами, относящимися к нашему асинхронному менеджеру. Его цели довольно просты: 1) хранить все константы async id, используемые в любом месте приложения, чтобы инженеры могли просматривать их в одном центральном месте, и 2) сохранять отображение активного времени на основе ключей i18n. Например, save соответствует saving. Мы используем i18n во всем нашем приложении, поэтому все переводится перед отображением пользователю, поэтому это сопоставление просто должно использовать наши ключи.

Компонент Button теперь выполняет простую задачу: если у него есть асинхронный идентификатор, проверьте список всех асинхронных идентификаторов и посмотрите, есть ли в нем асинхронный идентификатор текущего экземпляра. Если это так, измените время того, что видит пользователь, с помощью описанного выше сопоставления.

Конечный результат выглядит следующим образом: пользователь нажимает кнопку, чтобы что-то сохранить, кнопка становится неактивной, а метка меняется на «Сохранение…» во время вызова. После разрешения вызова кнопка возвращается в исходное состояние, и теперь пользователь видит сообщение об успешном выполнении (не связанное с этим обсуждением - это результат обмена сообщениями нашей основной системы).

Что это значит для инженера? Это означает, что чтобы получить желаемое поведение от кнопки, они просто добавляют асинхронный идентификатор к константам и используют эту константу как опору asyncId для кнопки И передают ее параметрам асинхронного вызова (мы используем ядро ​​requestHandler который принимает варианты). В качестве бонуса это работает для форм и всего остального в пользовательском интерфейсе. Чтобы добавить его к любому другому компоненту, достаточно просто добавить свойство, а затем использовать его, так что он очень расширяемый.

Самая большая победа, на мой взгляд, заключается в том, что это еще один способ сделать опыт разработчика отличным, а также обеспечить надежный пользовательский интерфейс.

Обо мне: я ведущий архитектор пользовательского интерфейса в RedLock https://www.redlock.io Проверьте нас и обязательно посетите нашу страницу карьеры по адресу http: //careers.redlock. io / если вам нравится решать крутые проблемы, работая над самой крутой технологией.