Как использовать глобальные URLSearchParams в node

Я пишу (клиентскую) библиотеку JavaScript (модуль node/angular). В этой библиотеке я использую класс URLSearchParams.

const form = new URLSearchParams();
form.set('username', data.username);
form.set('password', data.pass);

Поскольку это общая библиотека, она упакована как модуль npm. Однако при запуске mocha unit test я получаю сообщение об ошибке, что URLSearchParams не определен. Причина заключается в том, что node не имеет URLSearchParams в глобальной области, но должен быть импортирован с помощью require('url'):

$ node
> new URLSearchParams()
ReferenceError: URLSearchParams is not defined
    at repl:1:5
    at sigintHandlersWrap (vm.js:22:35)
    at sigintHandlersWrap (vm.js:73:12)
    at ContextifyScript.Script.runInThisContext (vm.js:21:12)
    at REPLServer.defaultEval (repl.js:340:29)
    at bound (domain.js:280:14)
    at REPLServer.runBound [as eval] (domain.js:293:12)
    at REPLServer.<anonymous> (repl.js:538:10)
    at emitOne (events.js:101:20)
    at REPLServer.emit (events.js:188:7)

Как я могу сделать URLSearchParams доступным для клиентского кода внутри node, чтобы я мог протестировать библиотеку с помощью mocha?

Это не работает:

> global.URLSearchParams = require('url').URLSearchParams
undefined
> new URLSearchParams()
TypeError: URLSearchParams is not a constructor
    at repl:1:1
    at sigintHandlersWrap (vm.js:22:35)
    at sigintHandlersWrap (vm.js:73:12)
    at ContextifyScript.Script.runInThisContext (vm.js:21:12)
    at REPLServer.defaultEval (repl.js:340:29)
    at bound (domain.js:280:14)
    at REPLServer.runBound [as eval] (domain.js:293:12)
    at REPLServer.<anonymous> (repl.js:538:10)
    at emitOne (events.js:101:20)
    at REPLServer.emit (events.js:188:7)

Ответ 1

Обновление: Node v10 имеет встроенную доступность URLSearchParams для глобального объекта, поэтому его можно использовать напрямую, как и предполагалось в вопросе.

Старые версии Node:

Один из вариантов - установить его как глобальный в стартовом скрипте бегуна:

import { URLSearchParams } from 'url';
global.URLSearchParams = URLSearchParams

Например, в Jest вы должны использовать setupTestFrameworkScriptFile чтобы указывать на приведенный выше сценарий запуска.

В качестве примечания: если вы хотите достичь аналогичного результата при создании пакета универсального кода на стороне сервера, вы можете добиться этого с помощью ProvidePlugin:

{
  name: 'server',
  target: 'node',
  // ...
  plugins: [
    // ...
    new webpack.ProvidePlugin({
      URLSearchParams: ['url', 'URLSearchParams'],
      fetch: 'node-fetch',
    }),
  ],
}

Ответ 2

В AWS Lambda, которая использует Node8.10, мне нужно было сделать:

const {URLSearchParams} = require('url')
const sp = new URLSearchParams(request.querystring)

или

const url = require('url')
const sp = new url.URLSearchParams(request.querystring)

Ответ 3

Я попробовал это, и он отлично работает, вот URL документации

const url = require('url');
const params = new url.URLSearchParams();

Ответ 4

Если мы хотим поддерживать большой диапазон версий nodejs в нашем приложении, мы могли бы использовать такой грязный код, как этот:

if(typeof URLSearchParams === 'undefined'){
    URLSearchParams = require('url').URLSearchParams;
}

Примечание: Это не лучшая практика, чтобы require с условием.