• Ошибка при запуске таска Gulp?

    6528d8858f8a4901424549.png
    Ответ написан
    Комментировать
  • Как решить долгий запрос blob?

    @risejs
    У тебя видео скачивается полностью. Если хочешь по частям, то надо сделать подобие потока. Blob для этого не подходит, то что в ссылке написано blob: не значит что URL.createObjectURL() принимает только Blob, там еще есть MediaSource.

    Потоковые медиа в браузерах работают через Media Source API. Видео для него должно соответствовать определенным требованиям, например фрагментированный mp4. Видео по твоей ссылке таким не является. Можно проверить здесь mp4info.

    Если для транспорта используется fetch или XMLHttpRequest, то есть парочка относительно простых способов это реализовать:

    1. Через тип ответа ArrayBuffer и заголовок запроса Range. В fetch поддерживается через response.arrayBuffer(), в XMLHttpRequest через responseType='arraybuffer'.
    Например.

    2. Через тип ответа ReadableStream (Streams API). В fetch поддерживается через response.body, в axios и других xmlhttprequest-основанных библиотеках не поддерживается. Также для Streams API требуется протокол HTTP/2+.
    Например 1, 2, 3, 4.

    Краткие примеры:
    const rangeVideo = async (player, mimeCodec, resource) => {
        const mediaSource = new MediaSource;
        player.src = URL.createObjectURL(mediaSource);
        await new Promise(resolve => mediaSource.onsourceopen = resolve);
        URL.revokeObjectURL(player.src);
        const sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
    
        const response = await fetch(resource, { method: 'HEAD' });
        const contentLength = response.headers.get('Content-Length');
        const segmentLength = 1 * 1024 * 1024;
        let fetchedLength = -1;
    
        while (true) {
            if (fetchedLength >= contentLength) break;
            const response = await fetch(resource, {
              headers:{'Range':`bytes=${fetchedLength+1}-${fetchedLength+=segmentLength}`}
            });
            const value = await response.arrayBuffer();
            sourceBuffer.appendBuffer(value);
            await new Promise(resolve => sourceBuffer.onupdateend = resolve);
            //console.count();
            //await delay(2000);
        }
    };
    
    const streamVideo = async (player, mimeCodec, resource) => {
        const mediaSource = new MediaSource;
        player.src = URL.createObjectURL(mediaSource);
        await new Promise(resolve => mediaSource.onsourceopen = resolve);
        URL.revokeObjectURL(player.src);
        const sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
    
        const response = await fetch(resource);
        const readableStream = response.body;
        const reader = readableStream.getReader();
    
        while (true) {
            const { value, done } = await reader.read();
            if (done) break;
            sourceBuffer.appendBuffer(value);
            await new Promise(resolve => sourceBuffer.onupdateend = resolve);
            //console.count();
        }
    };
    
    //const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
    
    const data = [
        document.querySelector('video'),
        'video/mp4; codecs="avc1.42E01E, mp4a.40.2"',
        'https://nickdesaulniers.github.io/netfix/demo/frag_bunny.mp4',
    ];
    
    //rangeVideo(...data);
    //streamVideo(...data);
    Ответ написан
    Комментировать
  • Проблема с цветом видео в разных браузерах?

    Aetae
    @Aetae Куратор тега JavaScript
    Тлен
    Конечно сталкивались, и простого решения конкретной проблемы нет: видео это немного отдельный поток и там всегда могут быть свои настройки отображения.

    Решения есть следующие:
    1. Делать видео сразу с прозрачностью, а не с бэкграундом, современные браузеры это поддерживают:
    2. Рисовать видео на canvas, программно подгоняя фон.
    3. Накладывать SVG фильтр на видео, который погонит фон.
    Ответ написан
    Комментировать
  • Как сортировать по индексу другого массива в js?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Сортировать по indexOf( ID ) в массиве, задающем порядок сортировки:
    var data = [
      {ID: 1, country: 'England'},
      {ID: 4, country: 'USA'},
      {ID: 9, country: 'Russia'},
      {ID: 5, country: 'Germany'},
      {ID: 6, country: 'France'},
    ];
    
    const order = [5,1,9,6,4];
    
    data.sort((a,b) => order.indexOf(a.ID) - order.indexOf(b.ID));
    
    /* [
      {"ID":5,"country":"Germany"},
      {"ID":1,"country":"England"},
      {"ID":9,"country":"Russia"},
      {"ID":6,"country":"France"},
      {"ID":4,"country":"USA"}]
    */


    На больших массивах для ускорения:
    1. добавить в исходный массив новое поле с порядковым номером, который каждый элемент должен занять после сортировки;
    2. отсортировать по этому полю.

    Так будет быстрее, чем на каждой операции сравнения двух элементов искать их индексы во втором массиве.
    data = data.map( e => {e.sortBy = order.indexOf(e.ID); return e;} );
    data.sort( (a,b) => a.sortBy - b.sortBy);
    Ответ написан
    Комментировать
  • Как изменять размер элемента при наведении на его край курсора мыши?

    MrDecoy
    @MrDecoy Куратор тега JavaScript
    Верставший фронтендер
    окей яндекс: custom resizable element
    https://habr.com/ru/articles/321612/
    Ответ написан
    5 комментариев
  • Почему в теле цикла не отображается консоль?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега JavaScript
    Когда вы сравниваете число с массивом, какой вы ожидаете результат?
    - i while(<= arr){
    + i while(<= arr.length){

    Более того, цикл у вас бесконечный, потому что i в нём не изменяется, так что это даже и хорошо, что он не запускается.
    Ответ написан
    1 комментарий
  • Замыкания не существует?

    Stalker_RED
    @Stalker_RED
    Я немного добавил наглядности
    function one() {
      const oneVar = 'Hello!'
      let counter = 0;
      console.log('функция one работает прямо сейчас, в счетчике', counter)
    
      function two() {
        console.log(oneVar, ++counter)
      }
      
      console.log('функция one почти завершилась, в счетчике все еще ', counter);
      return two
    }
    
    const three = one();
    console.log('функция one точно завершилась, даже return сработал');
    console.log('в переменной three сейчас функция two()');
    console.log(three);
    
    
    three();
    three();
    three();
    console.log('обожемой, мы видим как менялась переменная в уже завершенной функции. чераная магия? нет - это называется замыкание!');

    выхлоп:
    "функция one работает прямо сейчас, в счетчике", 0
    "функция one почти завершилась, в счетчике все еще ", 0
    "функция one точно завершилась, даже return сработал"
    "в переменной three сейчас функция two()"
    function two() {
      console.log(oneVar, ++counter)
    }
    "Hello!", 1
    "Hello!", 2
    "Hello!", 3
    "обожемой, мы видим как менялась переменная в уже завершенной функции. чераная магия? нет - это называется замыкание!"
    Ответ написан
    Комментировать
  • Почему обработчик реагирует на событие, случившееся до его установки?

    0xD34F
    @0xD34F Куратор тега React
    Я так понимаю, вот она, причина, подъехала с версией 18.0.0:

    Consistent useEffect timing: React now always synchronously flushes effect functions if the update was triggered during a discrete user input event such as a click or a keydown event.

    Т.е., жмёте на кнопку, открывается окно, запускается эффект, устанавливается обработчик клика на document, дальше событие клика по кнопке продолжило всплывать и попало в только что установленный обработчик.

    При добавлении задержки, данная проблема уходит

    Можете ещё попробовать ловить событие в фазе погружения:

    document.addEventListener('click', handleOutsideClick, true);
    return () => document.removeEventListener('click', handleOutsideClick, true);
    Ответ написан
    Комментировать
  • Как собрать строку, зная её символы и их индексы?

    0xD34F
    @0xD34F Куратор тега JavaScript
    вместо "Happy New Year!", я вижу это: "[object Object]appy New Year!"

    Здесь надо разобраться со следующими моментами:
    • Что делает метод reduce. Особое внимание следует обратить на то, какие параметры он принимает, и что происходит, если указать не все.
    • Как работает оператор +. Что бывает, если складываемые значения имеют различные типы.
    • Как значения одних типов преобразуются в значения других типов. Например, объект в строку.


    Сортировку применять не обязательно:

    const str = strArr.reduce((acc, n) => (acc[n.index] = n.char, acc), []).join('');
    Ответ написан
    Комментировать
  • Как сделать рамку в виде продолжения цифры?

    Ankhena
    @Ankhena Куратор тега CSS
    Нежно люблю верстку
    5 комментариев
  • Какая функциональная разница между этими подходами создания объектов в JS?

    Xuxicheta
    @Xuxicheta
    инженер
    допустим User это функция-конструктор, или класс.
    user = new User()

    будет создан объект, у которого есть свойство __proto__ в котором лежит объект, состоящий из одного свойства constructor, которая и есть ваша функция User. (Ну типа такой { constuctor: User }. Если писать через class то мы конструктор явно прям зададим. )
    Этот же объект лежит по адресу User.prototype, т.е.
    user.__proto__ === User.prototype
    Этот объект создается для любой объявленной функции (вообще не обязан, но в V8 вроде так), и например User.prototype.constructor === User

    Что такое метод класса, это функция по адресу User.prototype.sayHi (оно же лежит в user.__proto__.sayHi)
    Потом, когда мы пишем user.sayHi js проходит по цепочке из свойств __proto__ и ищет там эту функцию, вызывает ее и передает в качестве контекста (this) наш объект user.

    А теперь посмотрим разницу с вашим
    function User(x,y){
    let name = x;
    let age = y;
    
    return {
    name : name,
    age : age,
    sayHi: function(){
    console.log("My name is " + this.name);
    }
    }
    }


    тут все поля и функции лежат в одном объекте, который имеет только дефолтный __proto__ Object.prototype, автоматически присваиваемый при создании объекта через объектный литерал.
    При вызове функции несколько раз будут созданы несколько никак не связанных объекта. Прототип у них Object, это единственное что их роднит. Функции будут созданы каждый раз заново.
    user1.sayHi !== user2.sayHi
    Оператор instanceof не найдет у них общего предка User.

    Вот в этом и разница. Можно ли так писать? Можно, только зачем?
    Как назвать? Ну допустим функция-фабрика объектов. (не путатьс классом-фабрикой и со статическим фабричным методом, там создаются инстансы классов).

    Найдёте теперь сами разницу в ваших примерах 1 и 2?
    А так же почему в примере 1 new User() и просто User() дадут совершенно разный результат? И как сделать чтоб было одинаково?
    Ответ написан
    1 комментарий
  • Кроссбраузерность?

    sergey-gornostaev
    @sergey-gornostaev
    Седой и строгий
    Да.
    Ответ написан
  • Как равномерно заполнить 3 массива с учетом высоты элементов?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Ошибка в том что columnHeight нужно обновлять по тому же индексу, что и columns.
    Ну еще есть проблемы с тем, что исходные данные не упорядочены, а значит массивы будут заполняться не равномерно. Притом сортировать лучше по убыванию.
    Так же, если нужен оригинальный порядок, то его нужно сохранить, а потом так же восстанавливать сортировкой.

    // Сохраняем исходные индексы и сортируем по высоте по убыванию
    const preparedData = data
        .map((e, i) => ({i, e}))
        .sort((a, b) => b.e.height - a.e.height);
    
    for (const el of preparedData) {
        const { height } = el.e;
        // тут никогда не вернет -1, так как мы ищем элемент который точно есть в массиве - минимальный
        const index = columnHeight.indexOf(Math.min(...columnHeight));
        // обновляем данные массивов по выбранному индексу
        columnHeight[index] += height;
        columns[index].push(el);
    }
    
    // нормализуем columns
    for (let i = 0; i < columns.length; ++i) {
        // восстановим исходный порядок, отсортировав по сохраненному индексу по возрастанию
        columns[i].sort((a, b) => a.i - b.i);
        // избавимся от сохраненных индексов, оставив только исходные объекты
        columns[i] = columns[i].map(({ e }) => e);
    }
    Ответ написан
    Комментировать
  • Как работает этот JS со своим if?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    - if (duplicates.length = 0) {
    + if (duplicates.length === 0) {
    Ответ написан
    2 комментария
  • Что произошло с шрифтом?

    sfi0zy
    @sfi0zy Куратор тега CSS
    Creative frontend developer
    Без кода можно только гадать, что произошло в этом конкретном случае, но на ум сразу приходит свойство font-palette из CSS. Оно уже начинает поддерживаться в современных браузерах и некоторые энтузиасты его используют.

    Ответ написан
    1 комментарий
  • Как сделать продвинутый типизированный Generic для компонента React таблицы?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Надо явно создать union:
    type ITableColumn<
      DataInterface extends object, 
      Keys extends keyof DataInterface = keyof DataInterface
    > = {
      [K in Keys]: {
        key: K;
        title: React.ReactNode;
        hasSort?: boolean;
        render?: (item: DataInterface[K]) => React.ReactNode;
      }
    }[Keys];
    Ответ написан
    4 комментария
  • Как скопировать определенные (не все) свойства объекта?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Если в новом объекте должны быть все указанные свойства, вне зависимости от их наличия в исходном объекте:

    // имена свойств можно передавать в виде массива
    const pick = (obj, keys) => Object.fromEntries(keys.map(n => [ n, obj[n] ]));
    const newObj = pick(obj, [ 'b', 'c' ]);
    
    // или как отдельные значения
    const pick = (obj, ...keys) => keys.reduce((acc, n) => (acc[n] = obj[n], acc), {});
    const newObj = pick(obj, 'b', 'c');

    Если отсутствующие свойства не нужны:

    const pickExisting = (obj, keys) =>
      Object.fromEntries(keys.filter(n => n in obj).map(n => [ n, obj[n] ]));

    Если нужны только собственные свойства:

    const pickOwn = (obj, keys) =>
      keys.reduce((acc, n) => (Object.hasOwn(obj, n) && (acc[n] = obj[n]), acc), {});

    Если хотим выбирать свойства не только по именам, но и по значениям:

    const pick = (obj, filterFn) => Object.fromEntries(Object.entries(obj).filter(filterFn));
    
    const obj1 = pick(obj, ([ key, val ]) => 'abc'.includes(key) && val % 2); // {a: 1, c: 3}
    const obj2 = pick(obj, n => n[1] > 2); // {c: 3, d: 5}
    Ответ написан
    Комментировать
  • Как ловить разницу между моделями при общении клиент => сервер?

    yarkov
    @yarkov
    Помог ответ? Отметь решением.
    interface RequestModel<T> extends Request {
      body: T
    }
    
    class UserRegisterModel {
      first_name: string;
      last_name: string;
      email: string;
      password: string;
    
      constructor({first_name}) {
        this.first_name = firstname;
        // И так все НУЖНЫЕ поля
      }
    }
    
    app.post('/register', async (req: RequestModel<UserRegisterModel>, res) => {
      if(req.body) {
        const user = new UserRegisterModel(req.body);
        // Хоба и лишних полей нет ))
    }
    });
    Ответ написан
    Комментировать
  • Хочу написать свой интерпретатор языка программирования, в какую сторону копать?

    sergey-gornostaev
    @sergey-gornostaev Куратор тега Трансляторы
    Седой и строгий
    5cb2cd994a731133543905.jpeg
    Ответ написан
    Комментировать
  • Как работать с БЭМ и Sass в случае со вложенными элементами?

    delphinpro
    @delphinpro Куратор тега CSS
    frontend developer
    .block {
      &__element-2 {}
      &__element-1 {}
      &__element-1:hover &__element-2 {}
    }


    .block {
      $this: &;
      &__element-2 {}
      &__element-1 {
        &:hover #{$this}__element-2 {}
      }
    }


    и при повышении вложенности ситуация усугубляется


    Не нужно увеличивать вложенность. Это противоречит идеологии БЭМ.
    Ответ написан
    Комментировать