Автор явно не работал с этим серьезно. Тогда бы он упомянул то, о чем я написал в комментариях выше, а главное про то, что некоторые вендоры, особенно Китайцы, спецом ломают профиль, что бы видео нормально работало только в их клиентах. Я двух таких нашел, поток разбирал, смотрел каждый пакет, и искал в чем же косяк. Берут какой-то байт подменяют другим значением, из-за чего некорректно формируется профиль, условно говоря вместо hev1.2.3.e получается hev1.2.3.f — и вуаля, любой клиент говорит «я не знаю что это за кодек, воспроизвести не могу».
А в главном автор как раз ошибается. При одинаковых пресетах, и в одинаковых условиях (освещение, сцена и пр), две камеры разных производителей на одном и том же кодеке ведут себя вполне одинаково.
Что-то я не понял. Статья содержит очень много повторений одной и той же мысли, а главное — суть умещается в одну фразу: Есть кодеки, например H264 или H265, и у каждого кодека есть набор профилей, а от профиля зависит все остальное: битрейт, степень сжатия, фпс и прочее. Между H265 с восьми-битным 2К профилем и H265 шестнадцати-битным 8К профилем — огромная разница. Один может работать в вашем браузере, второй нет, при этом оба H265.
Да кто же вам генерирует эти дурацкие заголовки?! Каждая третья статья с тем же паттерном в заголовке [я/мы/он/она] [чё-то там] — и вот [как/почему/зачем]
Zod позволяет описать схему один раз — и получить сразу и тип, и рантайм-валидацию:
import { z } from 'zod';
const UserSchema = z.object({
id: z.number(),
name: z.string(),
email: z.string().email(),
});
type User = z.infer<typeof UserSchema>; // тип выводится автоматически
const getUser = async (): Promise<User> => {
const res = await fetch('/api/user');
const data = await res.json();
return UserSchema.parse(data); // если структура не та — бросит ошибку
};
Лично для меня этот подход крайне спорный, и я его не использую из следующих соображений:
Данные пришедшие с сервера по определению валидны, так как они проходят валидацию при сохранении. Нам не нужно проверять что поле email это правда емэйл. Да – правда. Его бы не занесли в базу будь он не валидным.
Проверять нужно только соответствие контракту: ждали строку – пришла строка, ждали свойство userName – пришло userName, а не user_name.
Можно валидировать данные перед отправкой, и для этого я использую Constraint Validation – min, max, pattern и пр.
Мне не нужны какие-то непонятные схемы, мне нужна конкретная модель сущнсти, и я предпочитаю rich models.
И для этого я написал себе библиотеку, которая решает мои задачи. То что вы называете схемой, у меня – модель:
import { Transformer } from 'kr-transformer';
class UserModel {
// Тип – строка
name = '';
// Тип – число
age = 0;
// тип – булево
student = false;
setName() {
// ...какой-то метод
}
get someComputation() {
return this.age * 3;
}
}
const json1 = { name: 'John', age: 42, student: true };
const json2 = { name: 'John', age: "42", student: true };
const json3 = { name: 'John', age: 42, student: null };
const json4 = { username: 'John', age: 42, student: false };
try {
// валидный JSON, ошибок нет
const model = Transformer.fromJSON(json1, UserModel);
} catch(error) {
console.log(error) //
}
try {
// age строка – невалидно
const model = Transformer.fromJSON(json2, UserModel);
} catch(error) {
console.log(error) // Unexpected type of <age>, expect Number but receive String
}
try {
// student null – невалидно
const model = Transformer.fromJSON(json3, UserModel);
} catch(error) {
console.log(error) // ...ошибка
}
try {
// username вместо name – невалидно
const model = Transformer.fromJSON(json4, UserModel);
} catch(error) {
console.log(error) // ...ошибка
}
То есть, полученный с сервера невалидный JSON, просто превратится в модель с понятной ошибкой. Модель сама по себе тип. С моделью дальше гораздо удобнее работать чем с каким-то json-ом.
Во-вторых, можете ли Вы привести сравнительные примеры того, как одни и те же задачи решаются без применения веб-компонентов и с применением веб-компонентов.
QA инженеры на своем селениуме. Есть сторя, для нее автотесты такой же артефакт как сборка. Эти тесты живут вместе с продуктом, и прогоняются при каждом инкременте
Не пишу никаких текстов вообще, уже года 4. Просто не вижу в этом смысла. Пока я пишу код, у меня открыт браузер и я сразу проверяю работу. Потом деплой, автотесты, ручное тестирование тестировщиками и нт. Если какой-то баг и закрался — найдут пользаки в проде, а правка дело плевое. Вообще не понимаю зачем тратить время на попытки сэмулировать браузер в ноде и что-то там тестировать. Как-то начал еще playwrite тесты писать, но потом и их выкинул.
Предположим, что мы это забатчим, что же мы получим? Ничего. Первый setAttribute меняет состояние элемента, и если это уместно, то произойдет какой-то painting или layouting. Потом второй, и процесс повторится. Потом третий. Какая разница, забатчили мы это или нет? Никакая. На любой вызов setAttribute, не важно откуда, браузер сделает свои дела, только в предлагаемом вами варианте мы добавляем дополнительную сложность без какого-либо профита.
В том же дейт-пикере нет особой необходимости хранить таблицы годов и месяцев в DOM и скрывать их через стили.
Никто так и не делает, разумеется. Там просто пара элементов в которых просто меняется контент.
Кроме того, подход, что мы просто меняем свойства (по сути состояние), и, когда придет время (когда окажется, что больше ничего не вызывает синхронные изменений свойств), тогда уже рендерим (обновляем) - это довольно знакомый шаблон.
Вы предлагаете создать состояние, и периодически синхронизовывать его с DOM. Это тот же React way. HTMLElement это уже состояние. Вызвав setAttribute или elem.prop = value мы как раз его изменяем, а браузер сделает свои дела, когда посчитает нужным.
Ну в общем, мне кажется, что вы мыслете в рамках реакта работая с веб-компонентами, по крайней мере такой вывод я сделал из этих комментариев. Это тоже подход, но я его не понимаю.
При переключениях месяцев у нас перестраивается таблица с числами
Все еще обновление уже существующих элементов. То есть у нас есть таблица с днями, условные 6 рядов по 7 колонок, и при изменении месяца, изменяется textContent у некоторых ячеек, а у некоторых, дополнительно еще и атрибут disabled. В таком кейсе нет причин убить одни, уже существующие элементы что-бы создать набор таких же, только с другим текстом.
При этом может меняться атрибут с отображаемым месяцем и годом
Та же историю, только еще проще. Количество и названия месяцев не меняется от года к году.
Я правда не могу представить ситуацию, когда было бы нужно убить одну разметку и создать новую, и мне еще не приходилось реализовывать что-то вроде метода render в своих компонентах, но даже если представить что такое потребуется, то все равно нет смысла в усложнении. Не нужно недооценивать производительность DOM API, это не React. Вот пример с комбобоксом из статьи: stackblitz, тут в нем 5000 опций с jsonplaceholder, при чем опции изначально рендерит React, и тем не менее, он работает без каких либо лагов, причем в песочнице, хотя в нем нет никаких специальных оптимизаций, и тем более виртуализации. Попробуйте что-то поискать, выбрать пару значений и т.д., а после, чтобы совсем отсеять любые сомнения поставьте атрибут selected всем опциям:
Не рассматривали ли Вы такой алгоритм.Создаем общую функцию рендера, в которой мы сравниваем значения атрибутов, и если изменились, только тогда меняем часть DOM.
Нет. Тут дело видимо в некорректных ассоциациях. Веб-компонент, это не реакт компонент, ему не нужно «ререндерится». Более того, сам ререндер в каком-то реакте тоже вводит в заблуждение. В реальности (на примере реакта) все устроено так: рендерится компонент, элементы вставляются в DOM, последующие ререндеры это изменение свойств/атрибутов уже вставленных в DOM элементов.
Тоже с веб-компонентом. То, что вы подразумеваете под рендером это вставка в DOM, и это происходит один раз – element.shaddowRot.innerHtml = someHtml. Это все. Изменение атрибута это просто изменение атрибута. При использовании с тем же реактом, это означает что произошли какие-то изменения, реакт ререндерит то, что у него называется компонентом, что в действительности приводит к вызову setAttribute у нашего элемента (и у других в разметке).
А в attributeChangeCallback мы добавляем батчинг операций с помощью очереди микрозадач. Что-то такое:
Это ничего не даст кроме дополнительной сложности или потребления памяти.
2) насколько легко использовать adoptedStyleSheets при разработке?
Никаких проблем. В нем хранятся стили перенесенные из lightDom, то есть их можно смотреть там. При дебаге (по крайней мере в хроме) adoptedStyleSheets доступны для просмотра.
Не рассматривали ли использование какого-либо статического свойства
Какой-то странный способ программировать. Вы или понимаете что код делает, или нет. Какая может быть подстраховка, если ясно что ссылку на объект держит Set, и пока он держит GC этот объект не очистит?
1) WeakRef дороги сами по себе 2) WeakRef немного тормозят GC 3) WeakRef немного тормозят event loop
Кроме того:
дочерний добавляется в children родителя, а ссылка на родителя хранится через WeakRef
Тут children просто Set, а не WeakSet, наличие в нем ссылки на EffectCb препятствует очистки WeakRef содержащее этот же EffectCb, а значит сама упаковка в WeakRef не имеет смысла.
Куда проще и дешевле была бы реализация через back-pointer.
Автор явно не работал с этим серьезно. Тогда бы он упомянул то, о чем я написал в комментариях выше, а главное про то, что некоторые вендоры, особенно Китайцы, спецом ломают профиль, что бы видео нормально работало только в их клиентах. Я двух таких нашел, поток разбирал, смотрел каждый пакет, и искал в чем же косяк. Берут какой-то байт подменяют другим значением, из-за чего некорректно формируется профиль, условно говоря вместо hev1.2.3.e получается hev1.2.3.f — и вуаля, любой клиент говорит «я не знаю что это за кодек, воспроизвести не могу».
А в главном автор как раз ошибается. При одинаковых пресетах, и в одинаковых условиях (освещение, сцена и пр), две камеры разных производителей на одном и том же кодеке ведут себя вполне одинаково.
Что-то я не понял. Статья содержит очень много повторений одной и той же мысли, а главное — суть умещается в одну фразу: Есть кодеки, например H264 или H265, и у каждого кодека есть набор профилей, а от профиля зависит все остальное: битрейт, степень сжатия, фпс и прочее. Между H265 с восьми-битным 2К профилем и H265 шестнадцати-битным 8К профилем — огромная разница. Один может работать в вашем браузере, второй нет, при этом оба H265.
Тест страница с разными профилями https://lf-tk-sg.ibytedtos.com/obj/tcs-client-sg/resources/video_demo_hevc.html
Да кто же вам генерирует эти дурацкие заголовки?! Каждая третья статья с тем же паттерном в заголовке [я/мы/он/она] [чё-то там] — и вот [как/почему/зачем]
Лично для меня этот подход крайне спорный, и я его не использую из следующих соображений:
Данные пришедшие с сервера по определению валидны, так как они проходят валидацию при сохранении. Нам не нужно проверять что поле
emailэто правда емэйл. Да – правда. Его бы не занесли в базу будь он не валидным.Проверять нужно только соответствие контракту: ждали строку – пришла строка, ждали свойство
userName– пришлоuserName, а неuser_name.Можно валидировать данные перед отправкой, и для этого я использую Constraint Validation –
min,max,patternи пр.Мне не нужны какие-то непонятные схемы, мне нужна конкретная модель сущнсти, и я предпочитаю rich models.
И для этого я написал себе библиотеку, которая решает мои задачи. То что вы называете схемой, у меня – модель:
То есть, полученный с сервера невалидный JSON, просто превратится в модель с понятной ошибкой. Модель сама по себе тип. С моделью дальше гораздо удобнее работать чем с каким-то json-ом.
https://habr.com/ru/articles/994666/
QA инженеры на своем селениуме. Есть сторя, для нее автотесты такой же артефакт как сборка. Эти тесты живут вместе с продуктом, и прогоняются при каждом инкременте
Потому, что некоторые не читают, а видят только то, что хотят видеть))
Некоторые увидели «я не пишу тесты», и для них это значит «нет тестов», хотя я написал:
Подержите мое пиво!
Не пишу никаких текстов вообще, уже года 4. Просто не вижу в этом смысла. Пока я пишу код, у меня открыт браузер и я сразу проверяю работу. Потом деплой, автотесты, ручное тестирование тестировщиками и нт. Если какой-то баг и закрался — найдут пользаки в проде, а правка дело плевое. Вообще не понимаю зачем тратить время на попытки сэмулировать браузер в ноде и что-то там тестировать. Как-то начал еще playwrite тесты писать, но потом и их выкинул.
Не только в Китае…
React way
React way + очень странное утверждение. Каким образом изменение свойства уже созданного HTML элемента засоряет DOM?
React way
Который как вы выше сами признаете – неэффективен.
React way
Вы буквально пытаетесь воссоздать React, но в этом нет смысла. Нужно перестроить в голове ментальную модель.
Предположим, что мы это забатчим, что же мы получим? Ничего. Первый setAttribute меняет состояние элемента, и если это уместно, то произойдет какой-то painting или layouting. Потом второй, и процесс повторится. Потом третий. Какая разница, забатчили мы это или нет? Никакая. На любой вызов setAttribute, не важно откуда, браузер сделает свои дела, только в предлагаемом вами варианте мы добавляем дополнительную сложность без какого-либо профита.
Никто так и не делает, разумеется. Там просто пара элементов в которых просто меняется контент.
Вы предлагаете создать состояние, и периодически синхронизовывать его с DOM. Это тот же React way. HTMLElement это уже состояние. Вызвав setAttribute или elem.prop = value мы как раз его изменяем, а браузер сделает свои дела, когда посчитает нужным.
Ну в общем, мне кажется, что вы мыслете в рамках реакта работая с веб-компонентами, по крайней мере такой вывод я сделал из этих комментариев. Это тоже подход, но я его не понимаю.
Все еще обновление уже существующих элементов. То есть у нас есть таблица с днями, условные 6 рядов по 7 колонок, и при изменении месяца, изменяется textContent у некоторых ячеек, а у некоторых, дополнительно еще и атрибут disabled. В таком кейсе нет причин убить одни, уже существующие элементы что-бы создать набор таких же, только с другим текстом.
Та же историю, только еще проще. Количество и названия месяцев не меняется от года к году.
Я правда не могу представить ситуацию, когда было бы нужно убить одну разметку и создать новую, и мне еще не приходилось реализовывать что-то вроде метода render в своих компонентах, но даже если представить что такое потребуется, то все равно нет смысла в усложнении. Не нужно недооценивать производительность DOM API, это не React. Вот пример с комбобоксом из статьи: stackblitz, тут в нем 5000 опций с jsonplaceholder, при чем опции изначально рендерит React, и тем не менее, он работает без каких либо лагов, причем в песочнице, хотя в нем нет никаких специальных оптимизаций, и тем более виртуализации. Попробуйте что-то поискать, выбрать пару значений и т.д., а после, чтобы совсем отсеять любые сомнения поставьте атрибут selected всем опциям:
и посмотрите с какой скоростью после получения данных с сервера, выбранные опции отобразятся.
Спасибо, приятно слышать.
Нет. Тут дело видимо в некорректных ассоциациях. Веб-компонент, это не реакт компонент, ему не нужно «ререндерится». Более того, сам ререндер в каком-то реакте тоже вводит в заблуждение. В реальности (на примере реакта) все устроено так: рендерится компонент, элементы вставляются в DOM, последующие ререндеры это изменение свойств/атрибутов уже вставленных в DOM элементов.
Тоже с веб-компонентом. То, что вы подразумеваете под рендером это вставка в DOM, и это происходит один раз – element.shaddowRot.innerHtml = someHtml. Это все. Изменение атрибута это просто изменение атрибута. При использовании с тем же реактом, это означает что произошли какие-то изменения, реакт ререндерит то, что у него называется компонентом, что в действительности приводит к вызову setAttribute у нашего элемента (и у других в разметке).
Это ничего не даст кроме дополнительной сложности или потребления памяти.
Никаких проблем. В нем хранятся стили перенесенные из lightDom, то есть их можно смотреть там. При дебаге (по крайней мере в хроме) adoptedStyleSheets доступны для просмотра.
Конечно, это упомянуто в статье: loadCssFromUrls и loadCssFromDocumentStyleSheets. Первый как раз вставит импорты соответствующих ссылок во внутренний
<style>.Зачем в статье про векторный поиск в postgresql, приводить код реализации crud на питоне? Канале это имеет отношение к теме?
Они уже давно это сделали)
Ясно, а когда сделаете чтобы видео не перезагружалось само, прямо во время просмотра?
Какой-то странный способ программировать. Вы или понимаете что код делает, или нет. Какая может быть подстраховка, если ясно что ссылку на объект держит Set, и пока он держит GC этот объект не очистит?
Очень даже значительное.
Слишком дорогой ценой.
1) WeakRef дороги сами по себе
2) WeakRef немного тормозят GC
3) WeakRef немного тормозят event loop
Кроме того:
Тут
childrenпростоSet, а неWeakSet, наличие в нем ссылки наEffectCbпрепятствует очисткиWeakRefсодержащее этот жеEffectCb, а значит сама упаковка вWeakRefне имеет смысла.Куда проще и дешевле была бы реализация через back-pointer.
А в ответ: хотите напишу вам драфт статьи, для публикации на таких популярных площадках как хабр или дев то?
Под стать статьи!
https://habr.com/ru/articles/992714/comments/#comment_29488678