Проверить url.format(urlObject)?

Меня интересует URL-адрес NodeJS API. В частности, метод url.format(urlObject). Я хотел бы создать функцию, которая проверяет urlObject перед вызовом формата и выдает TypeError, если какая-либо из пар ключ/значение объекта недействительна или «лишняя» (отсутствует в спецификации).

Есть ли способ, помимо типизации TypeScript, добиться этого?

даже машинописный текст не будет «проверять» эти объекты. Это предотвратит вызов атрибутов только для объекта, который не входит в данный тип.

messerbill 18.02.2019 21:42

@messerbill Это не скомпилируется. Вы поняли мой вопрос.

j_d 18.02.2019 21:43

он будет скомпилирован из-за того, что URL-адрес будет установлен во время выполнения... в противном случае я неправильно понял ваш вопрос. Хотя вы пытаетесь «проверить» значение urlObject и подтвердить его, ожидая, что некоторые недопустимые данные могут быть отправлены во время выполнения.

messerbill 18.02.2019 21:45
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
3
2 747
1

Ответы 1

Вам будет трудно это сделать, потому что при создании экземпляра URL:

u = new URL('http://example.com/');

и Object.keys(u), и Object.getOwnPropertyNames(u) вернут пустой массив, и даже JSON.stringify(u) здесь вам не поможет, поскольку в результате получается одна строка верхнего уровня, а не JSON-представление объекта.

Таким образом, вы не сможете легко проверить наличие каких-либо дополнительных полей, если только вы вручную не проанализируете вывод util.format(u) или что-то в этом роде, но вам все равно нужно будет проверять ключи объектов (включая неперечислимые свойства) для проверки других объектов. которые не являются экземпляром URL.

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

Но имейте в виду, что url.format() не нужен настоящий экземпляр URL, например. эти две строки имеют одинаковый эффект:

a = url.format(new URL('http://example.com/'));
b = url.format({ protocol: 'http', host: 'example.com', pathname: '/' });
// a === b

Чтобы проверить, имеет ли экземпляр URL (или любой другой объект) следующие свойства и являются ли они строками, как это должно быть в экземпляре URL, вы можете использовать что-то вроде:

const k = [
  'href',
  'origin',
  'protocol',
  'username',
  'password',
  'host',
  'hostname',
  'port',
  'pathname',
  'search',
  'hash',
];

const validUrl = u => k.filter(k => typeof u[k] === 'string').length === k.length;

Это вернет true для обычных URL экземпляров:

u = new URL('http://example.com/');
console.info(validUrl(u));

но и для других объектов, если они имеют все необходимые поля. Но имейте в виду, что для url.format() не требуются все поля, как вы можете видеть в примере выше, так что таким образом вы отклоните некоторые значения, которые идеально подходят для url.format(), например:

u = { protocol: 'http', host: 'example.com', pathname: '/' };

Подвести итог:

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

Чтобы увидеть, есть ли у него все необходимые (по вашему мнению — не обязательно по мнению url.format()!) свойства, вы можете написать простую функцию проверки, но тогда вы не сможете опустить пустые свойства, такие как username, если их нет, и вы придется явно передавать пустые строки для всех пустых свойств, если вы хотите иметь возможность использовать URL-подобные объекты, которые в остальном совместимы с url.format().

Возможно, вы хотите протестировать только некоторые поля, такие как протокол, хост и имя пути, но тогда вам придется смириться с тем, что url.format() примет либо host, либо hostname, предпочитая host, если доступны оба и т. д.

Вы также можете попробовать такой хак:

const testUrl = u => {
  try {
    new URL(url.format(u));
  } catch (e) {
    throw new TypeError('your error message');
  }
};

и иметь функцию, которая экспериментально проверяет, работает ли данное значение с url.format(), предоставляя URL-адрес, который может быть проанализирован new URL() следующим образом:

testUrl(new URL('http://example.com')); // ok
testUrl({host: 'example.com', protocol: 'http'}); // ok
testUrl({host: 'example.com'}); // throws a TypeError 

Теперь в вашей функции, которая вызывает url.format(urlObject), все, что вам нужно сделать, это добавить: testUrl(urlObject) в предыдущей строке, и она будет генерировать описанные вами исключения.

А вообще это сложный вопрос. Вы можете сделать это разными способами, но все они имеют некоторые недостатки. Экземпляры URL на самом деле довольно странные, и даже Джой ломается на них!

Например:

!joi.object({ host: joi.string().required() }).validate({ host: 'example.com' }).error;
// returns true

!joi.object({ host: joi.string().required() }).validate({ nohost: 'example.com' }).error
// returns false

!joi.object({ host: joi.string().required() }).validate(new URL('http://example.com/')).error;
// this throws an exception!
// TypeError: Cannot read property 'host' of undefined
// WTF???

Если даже Джой не может проверить экземпляры URL, значит, их не так просто проверить.

Надеемся, что некоторые из приведенных выше примеров сделают то, что вам нужно.

Другие вопросы по теме