Цитата:
|
планировщик задач и потоков
|
При проектировании SPA все элементы интерфейса пишутся как отдельные виджеты (даже ссылка - это отдельный виджет), т.е. любой виджет в любой момент времени может быть убит или добавлен. Виджет может состоять из более мелких виджетов и т.д. Виджету для инициализации могут быть нужные данные из базы.
Собственно проблема: когда инициализируются несколько виджетов одновременно, то повышается вероятность "фриза" вкладки или браузера, а когда у нас пользователь перешёл на новую страницу, то шанс фриза на 500 и более мс очень велик (конечно, если у вас не совсем простая страница). Фриз на более чем 100 мс уже чувствуется и раздражает.
Для решения проблемы используется планировщик задач: он прикидывает "вес" каждого виджета (каждый виджет если не задано явно имеет вес 1, т.е. вес виджета, который включает другие виджеты равен его весу + сумма весов всех вложенных виджетов).
Когда виджет говорит "отрендери" меня, то его задачка добавляется в планировщик, где стоит правило, что допустим общий вес всех активных задач должен быть не более 10, т.е. если виджет занимает нужно себе место, то он будет отправлен на рендеринг сразу, а если нет, то будет добавлен в очередь.
Когда виджет полностью проинициализировался, то он освобождает занятое место (т.е. вычитает свой вес из общего) и это даст возможность другим виджетам пойти на рендеринг.
Между "проверкой места" должен быть таймаут, т.е. действия не должны идти сразу же, иначе мы зафризем вкладку. У меня стоит 25мс таймаут, вполне норм работает.
Подчёркиваю нужен именно таймаут, т.е. никакой setImmediate или requestAnimationFrame не подойдёт, т.к. этот таймаут нужен чтобы отдать поток на другие задачи (поймать фокус мышки, обработать клик и т.д.), т.е. чтобы юзер не дожидаясь общей загрузки уже работал с интерфейсом. Когда мы пишем простое приложение, то за нас это делает браузер, но в SPA всё сложнее.
Я думаю не стоит говорить, что все нужные шаблоны должны быть заранее скомпилины на сервере и подключаться как простой JS
Усложняем задачу: очень часто для того, чтобы отрисовать новую страницу - мы должны грохнуть старую, а только потом рисовать новую и если это делать последовательно, то фриза не миновать. Опять та же стратегия с планировщиком, только теперь удаляем виджеты, но в тоже время там где уже можно начинаем инициализировать новые виджеты.
Ещё усложняем задачу: есть такие виджеты, которые в момент инициализации много чего считают и могут самостоятельно зафризить поток. Следовательно выносим что можно в Worker, но Worker - это тяжёлая штука, а не легковесный поток, как например в Rust или Erlang и там есть лимит на создание (точно не помню, вроде не больше 10), т.е. для работы с потоками опять делаем планировщик.
Вот такие дела
Цитата:
|
также интересны нюансы (можно перечислить хотя бы некоторые)
|
Лучше задавай вопросы, ибо про всё тут писать я устану
На вскидку часов 10 устной лекции можно только про одни нюансы сделать