• Как работает VPAID?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Стандарт VPAID описывает лишь интерфейс взаимодействия плеера с креативом.
    Внутри может быть абсолютно любой код, который может делать все что угодно в рамках своего контекста, в том числе тоже быть плеером, который подгрузит рекламу по VAST/VPAID.

    В VAST могут быть параметры для VPAID, но он не обязан их использовать. Он может сходить за рекламой на свой сервер, который ему заранее известен, или вообще воспроизводить рекламу, которая в него зашита.

    А может и не рекламу крутить, я например как то делал в виде VPAID интерактивную вакансию и таргетировал ее на IT'шников через рекламные сети.
    Ответ написан
    Комментировать
  • Как создать тип объекта?

    bingo347
    @bingo347 Куратор тега TypeScript
    Crazy on performance...
    type Obj = Record<'field1' | 'field2' | 'field3', number>;


    Еще так можно:
    const fields = ['field1', 'field2', 'field3'] as const;
    type Obj = Record<(typeof fields)[number], number>;
    Ответ написан
    Комментировать
  • Какой необходимый уровень TypeScript требуется для front-ende'ra?

    bingo347
    @bingo347 Куратор тега TypeScript
    Crazy on performance...
    Я лично задаю вопросы, чтоб выяснить понимает человек TS или придется учить. За свой обильный опыт проведения тех собеседований, по поводу TS отсеял лишь одного человека, с радикальными убеждениями вызванными парадоксом Блаба

    А так обычно проверяю базовое понимание, как TS работает и что в нем есть.
    Спрашиваю разницу между unknown и any.
    Могу дать задачку на infer или извлечение части типа.
    Поинтересуюсь, что нравится из последних новшеств.
    Ответ написан
    Комментировать
  • Как устранить ошибку TS2339: Property 'xxx' does not exist on type 'yyy'?

    bingo347
    @bingo347 Куратор тега TypeScript
    Crazy on performance...
    Комментировать
  • Как реализовать цикл на JS?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    У Вас функции popup1, popup2 и popup3 ничего не возвращают
    if (popup1() === random)соответственно здесь строго сравнивается undefined с числом, что всегда даст false.

    Вангуя следующий вопрос, сразу намекну, что prompt возвращает строку, и ее тоже так в лоб с числом не сравнишь.

    Ну и напоследок:if (agreement === true)зачем === true в условии, если agreement всегда типа boolean?
    Ответ написан
    1 комментарий
  • Можно ли так делать иконки?

    bingo347
    @bingo347 Куратор тега HTML
    Crazy on performance...
    Если картинка является контентом - ее вставляют через тег img с обязательным атрибутом alt, в котором по человечески расписано, что на картинке.
    Если картинка не является контентом, а содержит только некий визуал - ее вставляют через css background.

    Иконки, очевидно, не являются контентом, иконки - это вспомогательный визуал.
    По хорошему, иконки должны быть в формате svg или упакованы в векторный шрифт.
    Так же, если не стоит острый вопрос в едином стиле на всех ОС, то подавляющее большинство иконок уже есть в виде эмоджи в utf и присутствуют в системных шрифтах. Можно хорошо так сэкономить трафик пользователей.
    Ответ написан
    Комментировать
  • Как правильно выводить массив изображений canvas?

    bingo347
    @bingo347
    Crazy on performance...
    Проблема в том, что если присвоить в свойство src объекта Image новый url, то картинка не появится там моментально, она будет загружаться в фоне. Соответственно нужно дожидаться загрузки через событие, прежде чем рисовать.
    Ну и еще совет, если грузить картинки паралельно, каждую в свой Image, то будет быстрее.
    Ответ написан
    Комментировать
  • Как с помощью Node.JS вынуть ссылку на видео или фото?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    Комментировать
  • Как правильно распаковать данные в nodejs?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    научится пользоваться поиском по npm:
    https://www.npmjs.com/search?q=bz2
    Ответ написан
    Комментировать
  • Node+ts module-alias не работает с import, но работает с require?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    Typescript только резолвит пути из алиасов, но не переводит их в настоящие, оставляя это за сборщиками.

    Вариант 1: собирать проект с помощью webpack или rollup (или что Вам еще нравится)
    https://www.npmjs.com/package/@rollup/plugin-alias
    https://webpack.js.org/configuration/resolve/#reso...

    Вариант 2: захачить require/import в node (в зависимости от того, что на выходе у TS), чтобы понимало Ваши алиасы
    https://nodejs.org/dist/latest-v14.x/docs/api/esm....
    Для commonjs хука нет, нужно патчить вот это: https://nodejs.org/dist/latest-v14.x/docs/api/modu...
    Ответ написан
    Комментировать
  • Как правильно обрабатывать многомерные массивы в typeScript?

    bingo347
    @bingo347 Куратор тега TypeScript
    Crazy on performance...
    Проблема в ...form.formParams.errorList[formIndex]
    Давайте по порядку:
    // допустим у нас есть следующие переменные с типами:
    let obj: Obj;
    let value: T;
    
    // мы их собираем в такой объект:
    const newObj = { ...obj, k: value };
    тип для newObj компилятор будет выводить из контекста и получит Obj & { k: T }, ровно из того, что мы объединяем эти сущности.

    Усложним пример:
    let objs: Obj[];
    let value: T;
    let key: string;
    
    const newObj = { ...objs[1], [key]: value };
    Тип на выходе будет ужеObj & { [key: string]: string }, хотя objs на это раз у нас массив, компилятор видит, что мы берем индекс.

    Что будет, если objs вместо простого Obj[] у нас будет Obj[] | Obj[][]?
    Сначала мы берем значение по индексу из objs - эта операция вернет тип Obj | Obj[].
    После мы разворачиваем его через spread в объект и дописываем значение по индексу, получаем тип:(Obj | Obj[]) & { [key: string]: string }, тут еще Важно понимать, что типы в TS - это чистая математика, и данный тип полностью равносилен такому:
    (Obj & { [key: string]: string }) | (Obj[] & { [key: string]: string })

    А что, если Obj - это тоже { [key: string]: string }? Мы сможем свернуть тип, упростив уравнение на типах:
    (Obj & Obj) | (Obj[] & Obj)
    (Obj) | (Obj[] & Obj)
    (Obj & Obj[]) | (Obj & Obj)
    (Obj & Obj[]) | (Obj)
    Obj & Obj[]
    И это именно тот тип, который получил у Вас компилятор
    Ответ написан
    Комментировать
  • Как исправить ошибку used of moved value?

    bingo347
    @bingo347
    Crazy on performance...
    temp = temp.into_iter().rev().collect();
    (0..cols).for_each(|col| vec[row][col] = temp[col]);

    temp владеет некоторой памятью
    (0..cols).for_eachитерирует и вызывает переданную ему функцию cols раз
    замыкание преданное в for_each захватывает vec по &mut ссылке, а temp по значению
    на первой итерации temp[0] делает move в vec[row][0], так как в memory model Rust ни один тип не может существовать в виде "огрызка с дыркой", компилятор дописывает drop(temp) в конец функции |col| vec[row][col] = temp[col], а так как temp захвачен замыканием по значению (по сути он является частью замыкания), то в конце итерации цикла внутри for_each еще и само замыкание дропается.
    Другими словами for_each хочет от вас FnMut, а Вы ему дали только FnOnce.

    Думаю Вам поможет одна из этих функций:
    https://doc.rust-lang.org/beta/std/mem/fn.take.html
    https://doc.rust-lang.org/beta/std/mem/fn.replace.html

    index out of bounds: the len is 2 but the index is 2
    Это не ошибка компиляции, а runtime panic, которая говорит о там, что Вы вышли за границу слайса

    P.S. я надеюсь у Вас усть понимание, что здесь O(n3)?
    while (0..rows).map(|r| vec[r].first().unwrap()).all(|&x| x == 0) {
        (0..rows).for_each(|r| {vec[r].remove(0);});
    };
    Ответ написан
    Комментировать
  • Хайп вокруг ЯП Rust и C?

    bingo347
    @bingo347
    Crazy on performance...
    Насколько критичной проблемой для программиста является ручное управление памятью, которое называют недостатком языка Си?
    Неосвобожденная память (утечка памяти) - это самое безобидное, что может произойти.
    - Сделать free дважды - это UB
    - Забыли проверить результат malloc/calloc/realloc на не NULL, разыменовали - UB
    - Почитали память, в которую ни разу не писали - UB
    - Разыменовали указатель после free - UB
    - Гонка данных - UB
    - ...и еще дофига всего, от чего в лучшем случае программа просто будет работать неправильно, например спалит Ваш пароль, или переведет Ваши деньги на другой счет 10 раз.

    Новый язык программирования Раст, как заявляют, лишен этого недостатка

    Система типов Rust гарантирует лишь одно - в safe коде не будет UB. Утечка памяти, кстати, не является UB, поэтому память вполне себе можно утечь в safe коде, помимо циклических счетчиков ссылок std дает немало возможностей сделать это напрямую:
    https://doc.rust-lang.org/beta/std/mem/fn.forget.html
    https://doc.rust-lang.org/beta/std/mem/struct.Manu...
    https://doc.rust-lang.org/beta/std/boxed/struct.Bo...
    https://doc.rust-lang.org/beta/std/vec/struct.Vec....

    но разве число ошибок в программе зависит именно от наличия или отсутствия ручного управления памятью
    В Rust ручное управление памятью, как и в C и в C++, просто есть культура, что если некая структура аллоцировала память, то она ее освободит. Всякие Vec, Box и т.д. делают это в Drop. В C++ многие повседневные типы так же освобождают в деструкторе память, которую они выделили. Однако в Rust есть разделение на safe и unsafe код и для прикладного программирования safe возможностей более чем достаточно. В C++ же весь код unsafe.

    разве общее число ошибок не перераспределяется на другие недостатки программы
    Нет, не перераспределяется. Хорошая система типов действительно может избавить от многих ошибок, что в целом сделает ПО более надежным. Но надо понимать, что от всех ошибок не избавит ни что. Банальная дискоммуникация с заказчиком порождает огромное число багов.
    Но в Rust очень быстро привыкаешь к такому замечательному подходу в разработке, как Type Driven Development, который позволяет предупредить многие ошибки еще до написания кода. После Rust я стал применять этот подход и в других ЯП, и он работает очень хорошо, даже там, где типизация не такая строгая.

    являются ли ошибки с памятью ошибками программиста, а не компилятора и языка программирования
    Безусловно это ошибки программиста. Программисты, как правило, - это люди, а людям свойственно ошибаться. И хорошо, когда есть средства статического анализа, которые помогают предотвращать ошибки до выхода ПО в продакшн.

    P.S. Вот интересная статья про Rust к прочтению: https://steveklabnik.com/writing/a-sad-day-for-rust
    И к чему она привела: https://github.com/fafhrd91/actix-web-postmortem
    Ответ написан
    4 комментария
  • Как описать обобщённый ответ с restful api сервера?

    bingo347
    @bingo347 Куратор тега TypeScript
    Crazy on performance...
    Используйте дженерик параметры
    export type ApiResponse<T> =
      | { errors: Array<{ [key: string]: string }> }
      | { data: Array<T> }
      | { text: string };

    abstract class Api<T> {
      protected readonly baseUrl: string;
      protected readonly endPoint: string;
    
      protected get url(): string {
        return new URL(this.endPoint, this.baseUrl).toString();
      }
    
      protected constructor(baseUrl = '/', endPoint: string) {
        this.baseUrl = baseUrl;
        this.endPoint = endPoint;
      }
    
      protected async http({
        url = '',
        method = 'GET',
        data = undefined,
      }: RequestData): Promise<ApiResponse<T>> {
        try {
          const response: Response = await fetch(
            (new URL(url, this.url).toString()),
            { method, body: data }
          );
          return await response.json();
        } catch (e) {
          console.error(e.message);
          return { text: e.message };
        } finally {
          // finnally
        }
      }
    }

    class ApiPost extends Api<Post> {
      constructor(baseUrl: string, endPoint: string) {
        super(baseUrl, endPoint);
      }
    
      async list(count?: number): Promise<false | Array<Post>> {
        const response: ApiResponse = await this.http({
          url: `${count ? `?_limit=${count}` : ''}`,
        });
    
        if (Array.isArray(response))
          return response;
    
        return false;
      }
    }
    Ответ написан
    4 комментария
  • Как вытянуть ключ с обьекта который находится в массиве?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Ваша проблема в том, что у Вас массив объектов, а Вы пытаетесь с ним работать как с единственным объектом. Прежде чем работать с объектом, нужно получить ссылку на него из массива, например по индексу.

    Еще одна проблема, хоть она и не относится к вопросу, это то что у Вас присутствует бесполезная работа с localStorage (Вы каждый раз пишите туда новые, никак не зависящие от старых, данные, только ради того чтоб их тут же прочитать), а так же бесполезная сериализация/десериализация JSON.
    Отношение к пользовательским ресурсам - все равно что вломится к пользователю домой и плюнуть ему в лицо.
    Ответ написан
    Комментировать
  • Как скопировать файлы в папку Nginx через Node.js?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    1. Создать новую группу пользователей
    2. Добавить в нее пользователя nginx (обычно www-data) и пользователя из под которого запускается node
    3. Назначить эту группу владельцем папки, в которую нужно писать и открыть права на запись для группы
    Ответ написан
    Комментировать
  • Как правильно отправить на сервер и сохранить буфер загружаемого файла?

    bingo347
    @bingo347
    Crazy on performance...
    Во-первых, строки в JS в памяти хранятся в виде utf-16, а значит сохранение произвольного бафера в строку может сломать данные.

    Вот тут Ваши данные ломаются:
    let chunks = '';
    
    req.on('data', chunk => {
        chunks += chunk;
    });


    Во-вторых, не стоит читать файлы в память целиком. Память не резиновая, и однажды ее может просто не хватить.

    В-третьих, не нужно перекладывать байты из одного потока в другой руками, есть pipe, который делает это гораздо эффективнее.

    Отправка:
    const filePath = `../source/archive.zip`;
    const reader = fs.createReadStream(filePath);
    const options = {
        hostname: url.hostname,
        port: 443,
        path: url.pathname,
        method: 'PUT',
        headers: {
            'Content-Type': 'application/zip',
            'Content-Length': fs.statSync(filePath).size
        }
    };
    const req = https.request(options, res => {
        res.on('error', err => console.log('ошибка:', err));
        res.on('end', () => console.log('отправлено'));
    });
    reader.pipe(req);

    Получение:
    router.put('/', (req, res, next) => {
        const pathToFile = path.join(__dirname, '../public/uploads/archive.zip');
        const writer = fs.createWriteStream(pathToFile);
        req.pipe(writer).once('error', next).once('finish', () => {
            res.send('файл сохранён');
        });
    });
    Ответ написан
    4 комментария
  • Как сохранять события в localStorage js?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    localStorage.getItem сам не поставит класс элементу, он просто читает значение
    if (localStorage.getItem('theme') !== null) {
        localStorage.getItem('theme') // эта строка ничего не делает
    }


    Попробуйте так:
    (function () {
      const blue = document.querySelector('#pink')
    
      switch (localStorage.getItem('theme')) {
          case 'blueTheme':
              blue.classList.add('blueTheme')
      }
    
      blue.addEventListener('click', () => {
        if (blue.classList.contains('blueTheme')) {
            blue.classList.add('blueTheme')
            localStorage.setItem('theme', 'blueTheme')
        } else {
            blue.classList.remove('blueTheme')
            localStorage.removeItem('theme')
        }
      })
    }())
    Ответ написан
    Комментировать