Pull to refresh

Comments 35

Пользователя сильнее всего злит не время загрузки или парсинга, а отсутствие отзывчивости UI. «Тормозами» он называет ситуации, когда каждое действие сопровождается микроскопическими (порядка 0.1-0.3 сек) подлагиваниями.
Пользователь наводит курсор на ссылку/кнопку — а она подсвечивается активной только через 0.1 сек. Пользователь щёлкает по кнопке — и всё замирает на полсекунды, после чего отрабатывается анимация нажатой кнопки. Пользователь набирает текст — а символы появляются не одновременно с нажатием клавиш, а с ощутимой задержкой.
А теперь плохие новости: если вы используете навороченные фреймворки, всякие там ангуляры с реактами, то избавиться от таких «тормозов» вам будет очень и очень сложно. Потому что для этого придётся нанимать не индусов с почасовым рейтом $2, кодящих путём копипасты со stackoverflow, а настоящих профи, которые встречаются довольно редко и стоят дорого.
Сильно (зачастую на порядки) экономить на разработке за счёт удобства пользователя — это современный тренд, который вряд ли удастся переломить в ближайшие лет 10.
Я вообще считаю, что любой сайт должен быть доступен с отключёнными скриптами, пусть и не со всем функционалом. Но сейчас это не в моде, в тренде изоморфный рендеринг, веб-приложения и прочее перекладывание рендеринга на клиента, который, по мнению веб-программистов, простаивает. Самое смешное, что использование новомодных фреймворков далеко не всегда приводит к удешевлению разработки, а, наоборот, всё только удорожает и усложняется. И да, для crawler-ов поисковых систем отдать статику почему-то никаких проблем не вызывает.
Вот как раз правильно настроенный изоморфный рендеринг и позволяет читать сайт с отключенными скриптами.
изоморфный рендеринг

и прочее перекладывание рендеринга на клиента

взаимоисключающие параграфы
Я вообще считаю, что любой сайт должен быть доступен с отключёнными скриптами, пусть и не со всем функционалом.

Почему? Нет, я так тоже раньше считал, в основном по причине производительности, но я никогда не формулировал, что этого не должно быть никогда. Если это будет работать быстро — ок, никакой проблемы в этом не вижу. Клиент зачастую действительно простаивает.
Не забывайте, что у пользователя может быть очень слабый интернет (мобильный, WiFi в метро и т.д.). В случае статики клиент увидит страницу за один запрос. В случае скриптов это будет уже три запроса (получить HTML, получить файл с JS-скриптом, затем получить данные).

> Клиент зачастую действительно простаивает.

Вот именно, что зачастую. Но зачастую — не означает всегда. Вот я, например, люблю открыть сразу 10-20 вкладок, а потом по очереди их читать.
Не забывайте, что у пользователя может быть очень слабый интернет (мобильный, WiFi в метро и т.д.). В случае статики клиент увидит страницу за один запрос. В случае скриптов это будет уже три запроса (получить HTML, получить файл с JS-скриптом, затем получить данные).

Не видел ни 1 сайта в котором все данные в одном html. Причем даже когда на ADSL сидел.

Вот именно, что зачастую. Но зачастую — не означает всегда. Вот я, например, люблю открыть сразу 10-20 вкладок, а потом по очереди их читать.

Сложных вычислений на клиенте быть не должно. А т.к. большинство вычислений будут при активном взаимодействии, то это не проблема. Надеюсь, вы не скроллируете сразу в 10-20 вкладках.

Я люблю статику, но только потому, что современный HTTP хорошо с ним работает: стандартизирован механизм кэширования, браузер совершает меньше запросов, ну и на сервере есть всякие механизмы кэширования динамических страниц. Но это не непреложная истина, веб не обязан быть таким, и если браузер научится кэшировать JS-based сайты я буду только за. Отключение JS для меня не отличается от отключения CSS — можно конечно, но зачем? Стили-то браузер тоже считает, время тратит. Любая работа — это вычисления. С этим придется смириться. У интерактивных JS-интерфейсов есть преимущество как раз в том, что НЕ совершается запросов на сервер. Если вы заходите на один раз почитать анекдот, и грузите ради этого все скрипты — это не особо эффективно. Но если вы сидите на нем ощутимое количество времени, то вместо полной перезагрузки страницы браузер бросается легковесными XHR, а то и по вебсокету мгновенно обменивается. И это дает намного более приятный UX. Не считая про вышеупомянутые техники «сменить состояние кнопки, дождаться ответа, в случае ошибки откатить его на предыдущее и выдать сообщение об ошибки». В 99% случаев с сервера придет подтверждение. Ровно то же самое, что branch prediction в CPU :) Никто ж не говорит, что он обманывает, просто спекулирует, и как правило оказывается прав. Полезная штука.

Либо можно взять фреймворк, написанный профи и даже у индусов с его помощью будет всё летать. Например… $mol, основной целью разработки которого было обеспечение максимальной отзывчивости по умолчанию.

Качественный индус способен устроить тормоза при использовании любого фреймворка, а также и при неиспользовании оного.

Разница лишь в том, надо ли ему специально постараться, чтобы сделать медленно, или специально постараться, чтобы сделать быстро. В случае $mol, чтобы сделать медленно нужно приложить дополнительные усилия, что не свойственно качественному индусу.

Тем не менее у Вас, если мне не изменяет память, получилось сделать тормозной демо-страницу к вашей статье, в которой описывался подход используемый в данном фреймворке и рекламировался сам фреймворк;)

Если вы про http://toys.hyoo.ru то аналогичная намеренно тривиальная реализация на любом другом фреймворке грузилась бы целую вечность.

Если делать задачу в лоб методом Stack overflow driven development на jquery — то тормозить там будет только подгрузка новых картинок при достижении конца списка.

А у вас тормозит сайт при любом перемещении скрола, даже вверх! Просто потому что вы делаете слишком много вычислений внутрях обработчика события scroll.
тормозить там будет только подгрузка новых картинок при достижении конца списка.

Это потенциальному индусу ещё нужно осилить "дорендеринг". Если же он в лучших традициях напишет аналогичный код:


toy_cards() {
    return this.toys_sorted().map( toy => this.Toy_card( toy.id() ) )
}

То он сразу же отрендерит вообще все карточки, что может занять не один десяток секунд только лишь на открытие страницы. Да, дальше скроллинг будет шустрый, если на девайсе достаточно памяти, конечно.


А у вас тормозит сайт при любом перемещении скрола, даже вверх!

Типичный кейс использования каталога — последовательная промотка списка, а не теребоньканье скролла вверх-вниз. Сколько можно спекулировать на эту тему?

Вот в том и проблема, что вам проще рассуждать про типичный кейс пользователя, чем в 3-4 строчки исправить ошибку.

Потому и тормозят фреймворки, что очень многие поступают так же…

О какой ошибке идёт речь?

Великолепный перевод! А статья очень полезная и интересная. Сам для себя начал замечать то как именно скрыто время загрузки приложений и веб-страниц. Я отключил анимации на своём смартфоне и такой: "О ужас! Что с ним произошло? Почему он стал медленнее?" А потому что нет анимации, во время которой приложение прогружалось.
Нас все время обманывают, но обман во благо приятного пользования продукта — хороший обман

Не понимаю этой магической константы (80мс), которая была взята из «Scientific American» (из потолка?).

События, которые заканчиваются быстрее чем за 80 миллисекунд, проходят незамеченными для сознания

Киберспортсменам это скажите, особенно которые в файтингах соревнуются. Для них очень отличаются условные «меньше 50мс» и «больше 50мс» в различных latency. Или что, из каждого правила есть исключения? Все люди разные?..
События, которые заканчиваются быстрее чем за 80 миллисекунд, проходят незамеченными для сознания. Бьющий в бейсболе взмахивает битой по мячу прежде чем осознал, что питчер бросил его.

Есть разница для игрока, даже если она не осознаётся как прямая задержка
Для них очень отличаются условные «меньше 50мс» и «больше 50мс» в различных latency.
Что отлично согласуется с тем, что написано в статье. Про двойную буфферизацию не забыли?

Или что, из каждого правила есть исключения? Все люди разные?..
Да, разные. Где-то 10-15% физиологичесткие отличия в скорости реакции могут быть. Но, скажем, фальшстарт регистрируется если спортсмен реагирует быстрее, чем за 100мс
В таких ситуациях работают совершенно другие механизмы. Всегда идет работа на опережение. Вся система обучения боевым искусствам построена на предсказании действий противника и доведения до автоматизма ответных действий (вытеснение на уровень мозжечка что заметно сокращает latency, поскольку исключает работу медленных зон визуального тракта, дополнительно идет тренировка слуховых, осязательных трактов и бокового зрения).

В этой статье куча ошибок, касающихся тайминга, не уверен что автор копал достаточно глубоко. Вообще полное время реакции, от нового события до действия по визуальному тракту у лучших спортсменов не меньше 300ms. 60ms требуется глазу для ступенчатого трекинга движущегося объекта, если траектория уже предсказана.
Простите, но это какая-то чушь. Простой тест реакции «тыкни когда загорится» включает в себя как раз время от одного события (загорелось) до действия (тыкни). Типичное время в таком тесте: 150-250 мс. Попробуйте сами, и увидите, что даже у Вас это время ~200 мс, но уж никак не «у лучших спортсменов не меньше 300».
Вы сейчас совершили типичную ошибку, прочитали невнимательно о чем я писал не подумали :( «Вообще полное время реакции, от НОВОГО СОБЫТИЯ до действия по визуальному тракту у лучших спортсменов не меньше 300ms»
А вы попробуйте сбейте тарелочку выстрелом от бедра (само движение кстати занимает лишь 50ms а первые 250ms ничего не происходит у лучших спортсменов). Потом рассказывайте мне про 150ms.
А в вашем примере про 150-250ms речь идет только о триггере для готовой энграммы (в котором я вам и 10ms сделаю в некотором проценте, если сигнал окрашен), а ни о каком «НОВОМ СОБЫТИИ». В этом примере достижимы скорости порядка 100ms для этого и был пример известного факта из психофизических опытов про 60ms для трекинга по предсказанной траектории.

Проблема всей этой псевдо-ускоряющей лжи в том, что рано или поздно она вскрывается. Причем когда пользователь ложь обнаружил, он уже не может развидеть ее назад. Хуже того, создание иллюзии быстрой работы само по себе требует ресурсов. В результате пользователь будет ненавидеть вас дважды — за то что вы, вместо того чтобы взять и оптимизировать свое приложение, обмазали его прокрутками, анимациями и прочими прогресс-барами, а во-вторых за то, что все эти перделки сделали приложение ЕЩЕ МЕДЛЕННЕЕ, чем если бы всего этого не было.

UFO just landed and posted this here
В программе была функция, на которую пользователи жаловались что тупит, несколько секунд отрабатывает, так как функция вполне предсказуема, процесс был автоматизирован, операция периодически происходила в фоне, во временный файл.
Кнопка «Сохранить» лишь переименовывала готовый временный файл.
Но появилась другая жалоба, «Я уже два раза нажал но ничего не происходит.»
После этого пришлось добавить секундное отображение часиков вместо курсора, после нажатия кнопки.
Секундная задержка символизирующая сохранение результатов труда пользователя всех устроила.
А надо было не задержку вводить, а всего-то вывести всплывающее уведомление: «сохранение завершено».
Ровно таже самая мысль возникла, когда аналогичную проблему решили.
Кому в здравом уме придет в голову! ввести задержку! — представления не имею…
Не удивительно, что у нас всё тормозит…

Пользователь не осознал действие? Сообщение показать? Ну нафиг. Задержка!
Приложение крашится, потому что в декструкторе поток еще не завершился? Wait? Не, не слышал! Sleep(1000);
Приложение крашится при закрытии, потому что не всё корректно завершилось? Есть решение! Sleep(10000);
Не надо всплывающих уведомлений! Они тоже тормозят. Всего-то поменять вид кнопки (скажем, добавить зелёную галочку, типа, успешно сохранено).
И кстати, эти претензии «Я уже два раза нажал но ничего не происходит.» в основном происходят в силу исторически сложившихся обстоятельств, стереотипов. Например, если пользователь работал в какой-то программе на древнем компе, и кнопка «сохранить» приводила к интенсивной нагрузке, скажем, на диск; а потом диск сменили на SSD, и вместо 10 секунд задержка стала 0,1с — конечно, это не будет соответствовать ожиданиям пользователя (даже если стало лучше). Однако, если пользователь изначально работал в таких условиях, то такое поведение сочтёт в порядке вещей.
Что именно тормозят уведомления?
Скорее больше не тормозят, а раздражают.
Не знаю, меня больше всего раздражают фоновые штуки о которых я не просил. В идеале я бы хотел иметь что-то вроде:
1) Нажал на кнопку «Сохранить».
2) Начался процесс сохранения, кнопка поменяла статус (например, появилось колесико). Интерфейс, естественно, не заморожен.
3) Процесс закончился. Кнопка поменяла статус (например, появилась галочка)

Мне кажется, ленивое вычисление всего чего только можно — это лучший путь. К обратному лучше прибегать только в действительно критических секциях.
2) Начался процесс сохранения, кнопка поменяла статус (например, появилось колесико). Интерфейс, естественно, не заморожен.
Если «интерфейс, естественно, не заморожен», то это значит что фоновое сохранение в программе уже есть — только теперь оно запускается по запросу… но… зачем? Почему бы его в этом случае не производить «в фоне»? Во многих современных IDE кнопки «сохранить» вообще нет — и проблемы нет, сохранение занимает доли секунды и случается автоматически, так зачем вам ещё и кнопка какая-то?
Мне кажется это — естественная реакция. Если я произвёл действие, то должен обратную связь получить, что действие было совершено. Очень раздражает, когда нет никаких видимых признаков завершения или того, что вообще что-то происходит.
Sign up to leave a comment.

Articles