Ответы пользователя по тегу Node.js
  • Как сделать правильный shared проект?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    Вариант 1: монорепа
    Подойдёт если все 3 проекта будут в одном репозетории.
    Доп пакеты (вроде lerna) уже не нужны, используйте npm/yarn workspace
    https://docs.npmjs.com/cli/v10/using-npm/workspaces

    Вариант 2: установка из git
    Подойдёт если каждый проект в своём репо
    https://docs.npmjs.com/cli/v10/commands/npm-install
    Ответ написан
    Комментировать
  • Почему токен implements неожиданный, и кто его не ожидал?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    Нужно все транспайлеры подключать в jest, для ts лучше использовать ts-jest
    https://jestjs.io/docs/next/getting-started#via-ts-jest

    И кстати, вторая часть начинается именно с этого, нужно только внимательно читать
    https://github.com/romanovichim/TonFunClessons_ru/...
    Ответ написан
  • Как сделать Приложение под windows на JS без html?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Комментировать
  • Как организовать много app.use в express routers?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    Почитать документацию внимательно:
    https://expressjs.com/en/api.html#app.use

    app.use("/api", fooRouter, foooRouter, [fooooRouter, foooooRouter], fooooooRouter);
    Ответ написан
    1 комментарий
  • Как из JS сделать GET запрос с... Телом запроса?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    Если все в node работает, то используйте http/https request встроенный в нее:
    https://nodejs.org/dist/latest-v21.x/docs/api/http...
    https://nodejs.org/dist/latest-v21.x/docs/api/http...

    Да, придется самостоятельно в промисы обернуть, что несложно, но ограничений нет таких.
    Ответ написан
    3 комментария
  • Происходит ли блокировка при обращении к асинхронным роутам?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    async function выполняется синхронно до первого await
    Каждый встреченный по ходу выполнения await прерывает функцию, выкидывая из нее вверх по стектрейсу, в случае если это первый await, то продолжит исполняться функция, вызвавшая нашу, но там обычно тоже await, хотя и не обязательно. Так постепенно мы вывалимся в event-loop. Продолжение работы после await вызывается непосредственно из event-loop, так что в этом случае выше по стектрейсу будет только он.
    Когда исполнение в event-loop, он просто берет следующую задачу из очереди. Притом async function - это абстракция над промисами и их колбэками, а они выполняются в очереди микротасок, которую event-loop разбирает пока она не станет пустой.

    Если ближе к примеру в вопросе, то выполнение будет таким:
    1. event-loop вызовет колбэк http сервера, который часть роутера
    2. роутер вызовет наш колбэк, он это может делать как синхронно так и асинхронно (express делает синхронно)
    3. Наш колбэк отправит запрос в БД, получит его промис и остановится на await
    4. мы вернем управление роутеру, а он модулю http и в итоге все вернется в event-loop
    5. event-loop возьмет следующую таску из очереди, это может быть как запрос к http серверу, так и ответ от БД
    Ответ написан
    2 комментария
  • За счет чего Bun и Deno работают быстрее Node?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    У bun потенциально может быть быстрее старт приложения за счет использования движка JavaScriptCore вместо V8 в node/deno. Вот только у V8 на сегодня поддержка всех нюансов ECMAScript самая близкая к 100%. А старт рантайма происходит лишь 1 раз во время жизни приложения. Считать ли это профитом - вопрос философский.
    Ну и ИМХО, если биться за скорость путем смены движка, то я бы лучше взял QuickJS.

    Еще потенциальный выигрыш может быть за счет переписывания тех частей, что в node реализованы на JS. В node на самом деле очень многое на JS сделано. 100% встроенных модулей написано на JS, где уже под капотом дергаются функции из C++. Я не смотрел исходники deno/bun, но экспериментировал с v8 на Rust (спасибо deno за нормальный биндинг). Работать это будет быстрее, вот только обрабатывать JS Promise из нативки то еще приключение, и хочется делать это пореже за счет JS прослоек, как собственно и происходит в node.
    Rust (deno) и Zig (bun) по скорости сравнимы с плюсами (где-то быстрее, а где-то медленнее, но в среднем примерно одинаково). Самый большой оверхед в языках с рантаймом создает рантайм (сборка мусора, JIT компилятор и т.д.), у C++, Rust и Zig подкапотного рантайма почти нет, у JS - целый V8/другие движки.

    Ну и еще момент, что bun, что deno работают с ts из коробки. Вот только TypeScript - это язык у которого нет спеки, есть открытый код компилятора (в котором черт ногу сломит), есть release notes, а спеки нет. А значит гарантировать 100% совместимость с tsc не может никто. Хотя это проблема не только этих сред, но еще и WebStorm и babel-typescript например. Хотя на сколько понял они пошли путем babel - просто затранспайлить (по сути выкинуть все типы), вот только babel в некоторых кейсах все же ломает код...
    Ответ написан
    1 комментарий
  • Почему реджекшн главного промиса не перехватываться блоком .catch?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    Как я понимаю, этот .catch должен перехватить реджект главного
    промиса, но эта часть в принципе не выполняется и выходит
    ошибка UnhandledPromiseRejection

    Не должен, он с ним никак не связан.
    Ответ написан
    1 комментарий
  • Как происходит исполнение кода в Event Loop и управление потоками для веб приложений?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    1. Как происходит связь между кодом js, c++. На самом гитхабе Nodejs можно открыть папки с функциями, которые я импортирую в коде. А также их реализации в файлах .cc расширения. Но не могли бы подробнее описать механизм, которые позволяет 2 разных языка использовать.
    JS движок (например V8) предоставляет платформе (Node.js) некоторый C++ api, через который платформа может движком управлять. Например через это api можно дать движку строчку с JS кодом и попросить его выполнить, а в ответ получить указатель на результат выполнения (V8 например возвращает результат последнего выражения в коде). Так же, если у нас есть указатель на JS функцию, можно попросить движок ее выполнить с определенными аргументами и this, а в ответ получить результат этого выполнения (функция что-то вернула или бросила исключение). Ну и наконец, мы можем дать этому api указатель на C/C++ функцию, а движок сделает из нее JS функцию и вернет указатель на нее, когда JS функция вызывается движок вызовет нашу C/C++ функцию и даст ей на вход контекст выполнения, из которого можно извлечь this и аргументы функции, так же через контекст можно установить результат выполнения JS функции, указав что JS функция должна вернуть некоторое JS значение или бросить некоторое исключение.

    2. V8 - движок для исполнения JS кода, то есть превращения его в машинный код для исполнения комманд. Libuv написана на с++. Они же не работают в паре? Я так понимаю, что часть кода исполняется на движке v8, а различные асинхронные вызовы, которые через Nodejs api делегируются библиотеке Libuv - уже от неё превращаются в низкоуровневый машинный код, который исполняется компьютеров?Можете чуть пролить свет на исполнения уже между этими компонентами Libuv, V8.
    V8 ничего не знает о libuv, как и libuv ничего не знает о V8.
    V8 занимается компиляцией/интерпретацией/выполнением JS кода, управлением JS памятью и некоторыми другими связанными с JS вещами. В V8 нет никаких event loop и чего-то подобного, он запускает JS код только когда ему об этом скажет платформа (например Node.js).
    Libuv занимается асинхронными операциями. Что-то переадресует операционной системе, например сетевые сокеты можно собрать в пачку и отдать в epoll в Linux или kqueue в MacOS, заблокировав лишь один поток сразу на тысячи сокетов. А что-то просто блокируется на фоновых потоках, например обращения к файловой системе. Event loop нет и здесь, но зато есть очередь задач, которые потенциально готовы.
    Ну и наконец сама платформа (Node.js) реализует event loop (по сути просто бесконечный цикл), в котором получает потенциально готовые задачи от libuv и раскладывает по своим очередям готовые, а неготовые планирует в libuv, спрашивает у V8 не хочет ли он сделать сборку мусора, ну и наконец говорит V8 вызвать некоторые JS функции.

    3. После того, как Nodejs передает асинхронный вызов Libuv на исполнение. То callback функция помещается позже в стэк для исполнения, а исполнятся начинается после того, как система просигнализирует о завершении процесса, например считывания файла. Или вначале считывается файл, а потом система об этом сигнализирует и помещается callback функция в стэк Event Loop'a для исполнения?
    Выше уже расписал как Node.js взаимодействует с libuv в теле event loop, так же расписал как JS код может вызвать C++ функцию. Рассмотрим на сильно упрощенном примере, что происходит когда в JS коде на Node.js мы вызываем fs.readFile(filepath, callback):
    1. fs.readFile - это обычная JS функция, но внутри она вызывает некоторую C++ функцию из Node.js, которая получает указатель на строку filepath и указатель на JS функцию callback, но эта C++ функция будет запущена на том же потоке где и event loop (по сути где-то внутри цикла), а блокировать нам нельзя. Поэтому она просто планирует вызов другой C++ функции на фоновых потоках и завершается, возвращая тем самым управление JS коду.
    2. В какой-то момент до запланированной C++ функции дойдет очередь на выполнение на одном из фоновых потоков, она прочитает файл в память и добавит в очередь готовых задач некоторый объект, который является результатом операции чтения из файла, этот объект будет хранить в себе указатель на прочитанные данные и указатель на JS функцию callback.
    3. Еще через некоторое время поток с event loop извлечет из очереди этот объект результат и скажет V8 вызвать функцию callback с данными из файла.

    4. Можете более подробней рассказать про исполнение кода на инстансах приложения в зависимости от количества ядер процессора и управления потоками:

    4.1 Есть к примеру приложений на Nodejs. На компьютере 4 ядра. Я на каждом ядре могу запустить инстанс этого приложения. И у каждого инстанса в pool thread'e будет по 4 потока дополнительных, которые создаются по умолчанию?
    Каждый инстанс Node.js - это отдельный процесс операционной системы. У каждого процесса своя изолированная память. И да, каждый может запускать несколько потоков (у Node.js кстати 4 потока - это минимум, при большой нагрузке она может добавить в пул до 128 потоков), но в случае с Node.js большая часть потоков почти всегда что-то ждут (пока тот же файл прочитается например) и почти не тратят ресурсы CPU, а активно работает лишь один - тот в котором event loop.

    4.2 Если отойти от ноды и запустить приложение на php фреймворке на Apache и этот сервер выделяет под каждый запрос свой поток.В данном случае - это такой же условно поток, который может выделяться и библиотекой Libuv или это абсолютно разные понятия? И сколько инстансов php приложения запущено, когда Apache под каждый создает свой поток? Как соотносится поток с инстансом приложения на php.
    С точки зрения операционной системы - да, это такие же потоки. Разница заключается в том, что в этих потоках происходит. В php только 1 поток, который то что-то полезное делает, то ждет ответа от БД/файловой системы/еще чего-то. А в Node.js это разделено, 1 поток занят только полезной работой (выполнением JS кода) и несколько только ждут ответа.
    Насчет какие там лимиты на количество инстансов php у Apache я не скажу, но они точно не бесконечные, а значит если лимит будет исчерпан, то клиенты (браузер) будут ждать пока какой-то из инстансов php не завершит свою работу полностью. А в node.js мы на одном инстансе можем обслуживать сразу множество клиентов, выполняя задачи для каждого по чуть-чуть, пока для одного клиента ждем ответ из БД можем заняться обработкой запроса от другого клиента.

    4.3 Может в дополнение расскажите про потоки в системе, их ограничения и т.д
    Тут целую лекцию можно читать. Думаю это стоит вынести в отдельный вопрос.
    Ответ написан
    3 комментария
  • Как установить tinycbor | npm i tinycbor, у всех так c ошибкой не собираеются addon на Node.js error: cannot convert 'v8::MaybeLocal' to 'v8::Local'?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    Данный пакет использует "классическое" C++ api для аддонов вместо napi, которое как правило меняется с каждой мажорной версией node.js.
    Так как данный пакет последний раз опубликован 6 лет назад, то вряд ли его когда-то обновят под 18 версию.
    Я бы поискал другой пакет для CBOR, благо их не мало написанных на самом JS, а не в виде аддонов.
    Ответ написан
  • Ошибка Cannot read properties of null (reading 'id'), что сделать?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    Если правильно помню, то channel.guild существует только если канал, в котором активирован бот находится на каком-либо сервере.
    Соответственно оно будет null, если например активировать бота, написав команду ему в личку.

    Можно так:
    const channelId = channel.id;
    const guildId = channel.guild?.id;
    const adapterCreator = channel.guild?.voiceAdapterCreator;
    
    if (!channelId || !guildId || !adapterCreator) {
      message.channel.send(`Please log into the voice channel`);
      return;
    }
    
    if (command === 'join') {
      const connection = joinVoiceChannel({
        channelId,
        guildId,
        adapterCreator
      });
      message.channel.send(`Already here !`);
    }
    Ответ написан
    Комментировать
  • Почему не скачивается установщик NodeJS?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    Попробуйте отсюда скачать:
    https://nodejs.org/dist/latest-hydrogen/
    Ответ написан
  • Как реализовать?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    Комментировать
  • Пишет Cannot use import statement outside a module, что сделать?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    Во-первых, нода ничего не знает ни о каких config.json, резолвинг модулей еще смотрит на package.json и то лишь на некоторые поля.
    Во-вторых, es-modules должны иметь расширение .mjs в node.js, а .js и .cjs рассматриваются как common-js модули, для .js можно поменять поведение через флаги командной строки при запуске node.
    В-третьих, common-js модуль нельзя напрямую импортировать из es-module, благо я давным давно сделал хелпер для этих целей: https://www.npmjs.com/package/commonjs-variables-f...

    Подробнее обо всем этом можно почитать тут:
    https://nodejs.org/dist/latest-v18.x/docs/api/esm.html
    Ответ написан
    Комментировать
  • Как отобразить процесс работы в терминале?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    setTimeout(function f(percent) {
        if (!process.stdout.isTTY) return;
        if (percent > 100) {
            process.stdout.write('\n');
            return;
        }
        const FILL = 9608;
        const SHADE = 9617;
        const progressSize = process.stdout.columns / 2;
        const fillSize = Math.ceil(progressSize * percent / 100);
        const shadeSize = Math.floor(progressSize) - fillSize;
        const fillText = String.fromCharCode(FILL).repeat(fillSize);
        const shadeText = shadeSize > 0
            ? String.fromCharCode(SHADE).repeat(shadeSize)
            : '';
        process.stdout.clearLine();
        process.stdout.write(`\r${fillText}${shadeText} ${percent}%`);
        setTimeout(f, 250, percent + 1);
    }, 100, 0);

    https://nodejs.org/dist/latest-v18.x/docs/api/tty.html
    https://unicode-table.com/en/blocks/block-elements/
    Ответ написан
    Комментировать
  • Существует ли способ быстро запускать текущий файл в среде NodeJS?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    1. В корне проекта создайте папку .vscode (если ее еще нет)
    2. Создайте в папке .vscode файл tasks.json со следующим содержимым:
    {
      "version": "2.0.0",
      "tasks": [
        {
          "label": "Run current file in node.js",
          "type": "shell",
          "command": "node",
          "args": ["${file}"]
        }
      ]
    }
    Если такой файл уже есть, то просто дополните массив tasks содержимым выше.
    3. Нажмите Ctrl+Shift+P и введите команду Preferences: Open Keyboard Shortcuts (JSON), должен открыться файл keybindings.json, добавьте в конец массива следующий объект:
    {
      "key": "alt+f5",
      "command": "workbench.action.tasks.runTask",
      "args": "Run current file in node.js",
      "when": "editorTextFocus && editorLangId == javascript"
    }


    Все, теперь по Alt+F5 в тектовом редакторе будет запускаться текущий файл нодой, если он js файл
    Ответ написан
    1 комментарий
  • Как указать типы данных в импортируемом json файле?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    https://www.typescriptlang.org/tsconfig#resolveJso...

    Ну или создайте рядом с db.json файл db.json.d.ts со следующим содержимым:
    declare const JSON: {
        id: number;
    }[];
    export default JSON;
    Ответ написан
    Комментировать
  • Js проверка isset?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Оператор ! - это булево отрицание. И он приводит свой аргумент к типу boolean. Автор не открыл Америку, и это используется. Но использовать нужно с умом.
    Значения приводимые к false - это undefined, null, '' (пустая строка), 0, 0n (bigint 0), NaN.
    Соответственно, когда у нас есть например строка или undefined или например число или undefined - такая проверка на undefined может быть небезопасна, так как она отсечет еще и пустую строку, 0 и NaN.

    !! - это всего лишь 2 идущих подряд оператора !, это такое популярное сокращение для быстрого каста к boolean.
    Еще автор статьи предлагает использовать !!!, но это бессмысленно, так как тройное отрицание даст тоже самое что и одинарное.
    Ответ написан
    1 комментарий
  • Какой подход к проектированию бэкенда лучше? В чем принципиальная разница между подходами?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    Иначе говоря, в ООП-шном стиле и в функциональном (если я правильно понимаю).
    в обоих случаях процедурный стиль

    Пока возникает ощущение, что всё это - сугубо вкусовщина
    По сути да, чисто вкусовщина.
    Хотя второй вариант будет лучше сжиматься terser'ом если поменять
    const controller = { login }
    export default controller
    на export default loginНо для ноды terser редко используют
    Ответ написан
    Комментировать
  • Как убрать порт из адресной строки?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    Порты по умолчанию - это 80 для HTTP и 443 для HTTPS, о них браузер знает и прячет.
    Если нужен другой порт - никак не спрятать, иначе как браузер узнает, какой порт ему использовать кроме как из URL?
    Ответ написан
    2 комментария