Перевод: Лю Сяоси
Оригинальная ссылка:Dev induct.com/blog post/36…
Другие статьи можно нажать: GitHub.com/Иветт Л.А. Ю/Б…
Что такое прокси
Обычно, когда мы говорим о языке JavaScript, мы говорим о новых возможностях, предоставляемых стандартом ES6, и эта статья не стала исключением. Мы обсудим прокси-серверы JavaScript и то, что они делают, но прежде чем мы углубимся в это, давайте посмотрим, что такое определение прокси-сервера.
Определение в MDN таково: прокси-объект — это пользовательское поведение, используемое для определения основных операций (например, поиск свойств, присвоение, перечисление, вызов функции и т. д.).
Другими словами, мы можем сказать, что прокси-объект — это оболочка вокруг нашего целевого объекта, где мы можем манипулировать его свойствами и предотвращать прямой доступ к нему. Вам может быть трудно применить их к реальному коду, я рекомендую вам внимательно прочитать концепцию, это может изменить вашу точку зрения.
период, термин
handler
Объект-заполнитель, содержащий ловушки.
traps
Методы, обеспечивающие доступ к свойствам. Это похоже на концепцию ловушек в операционных системах.
target
Прокси виртуализированные объекты. (фактический объект, обернутый и управляемый прокси-объектом)
В этой статье я будуget
а такжеset
Подводные камни предоставляют простые варианты использования, учитывая, что в конце мы увидим, как их использовать, и включим более сложные функции, такие как API.
Синтаксис и варианты использования
let p = new Proxy(target, handler);
Передайте цель и обработчикProxy
конструктор, который создает прокси-объект. Теперь давайте посмотрим, как этим воспользоваться. Чтобы более четко увидеть преимущества Proxy, во-первых, нам нужно написать код без него.
Представьте, что у нас есть пользовательский объект с несколькими свойствами, мы хотим напечатать информацию о пользователе, если свойство существует, и создать исключение, если оно не существует. Когда прокси-объект не используется, код для оценки того, существует ли значение атрибута, также помещается в функцию, которая печатает информацию о пользователе, т. е.printUser
in (это не то, что нам нужно), как показано в следующей демонстрации:
let user = {
name: 'John',
surname: 'Doe'
};
let printUser = (property) => {
let value = user[property];
if (!value) {
throw new Error(`The property [${property}] does not exist`);
} else {
console.log(`The user ${property} is ${value}`);
}
}
printUser('name'); // 输出: 'The user name is John'
printUser('email'); // 抛出错误: The property [email] does not exist
get
Взглянув на приведенный выше код, вы обнаружите, что: переместите условие и исключение в другое место, в то время какprintUser
Было бы лучше просто сосредоточиться на фактической логике отображения информации о пользователе. Здесь мы можем использовать прокси-объекты, давайте обновим этот пример.
let user = {
name: 'John',
surname: 'Doe'
};
let proxy = new Proxy(user, {
get(target, property) {
let value = target[property];
if (!value) {
throw new Error(`The property [${property}] does not exist`);
}
return value;
}
});
let printUser = (property) => {
console.log(`The user ${property} is ${proxy[property]}`);
};
printUser('name'); // 输出: 'The user name is John'
printUser('email'); // 抛出错误: The property [email] does not exist
В приведенном выше примере мы обернулиuser
объект и устанавливаетget
метод. Этот метод действует как перехватчик, перед возвратом значения сначала проверяется значение свойства, и выбрасывается исключение, если оно не существует.
Результат такой же, как и в первом случае, но на этот разprintUser
Функция фокусируется на логике и обрабатывает только сообщение.
set
Другой пример прокси, который может быть полезен, — это проверка значения атрибута. В этом случае нам нужно использоватьset
метод и проверьте в нем. Это очень полезный хук, когда, например, нам нужно обеспечить целевой тип. Давайте посмотрим на фактическое использование:
let user = new Proxy({}, {
set(target, property, value) {
if (property === 'name' && Object.prototype.toString.call(value) !== '[object String]') { // 确保是 string 类型
throw new Error(`The value for [${property}] must be a string`);
};
target[property] = value;
}
});
user.name = 1; // 抛出错误: The value for [name] must be a string
Это довольно простые случаи использования, когда прокси может пригодиться:
- формат
- модификаторы значения и типа
- привязка данных
- отладка
- ...
Теперь пришло время создать более сложный корпус использования.
API с прокси — более сложный пример
Используя знания из простого варианта использования, мы можем создать оболочку API для использования в нашем приложении. В настоящее время поддерживается толькоget
а такжеpost
запроса, но его можно легко расширить. Код показан ниже.
const api = new Proxy({}, {
get(target, key, context) {
return target[key] || ['get', 'post'].reduce((acc, key) => {
acc[key] = (config, data) => {
if (!config && !config.url || config.url === '') throw new Error('Url cannot be empty.');
let isPost = key === 'post';
if (isPost && !data) throw new Error('Please provide data in JSON format when using POST request.');
config.headers = isPost ? Object.assign(config.headers || {}, { 'content-type': 'application/json;chartset=utf8' }) :
config.headers;
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest();
xhr.open(key, config.url);
if (config.headers) {
Object.keys(config.headers).forEach((header) => {
xhr.setRequestHeader(header, config.headers[header]);
});
}
xhr.onload = () => (xhr.status === 200 ? resolve : reject)(xhr);
xhr.onerror = () => reject(xhr);
xhr.send(isPost ? JSON.stringify(data) : null);
});
};
return acc;
}, target)[key];
},
set() {
throw new Error('API methods are readonly');
},
deleteProperty() {
throw new Error('API methods cannot be deleted!');
}
});
Объясним простую реализацию,set
а такжеdeleteProperty
. Мы добавили уровень защиты, чтобы гарантировать, что всякий раз, когда кто-то случайно или непреднамеренно попытается установить новые значения для любого свойства API, возникнет исключение.
Вызывается каждый раз, когда вы пытаетесь удалить свойствоdeleteProperty
метод. Можно гарантировать, что никто не сможет удалить какие-либо свойства из нашего прокси (например, здесь API), потому что обычно мы не хотим терять методы API.
get
Здесь интересно, он делает несколько вещей.target
пустой объект,get
метод будет использоваться в первый раз, когда кто-тоapi
создать все методы (например, текущийget
а такжеpost
просьба), вreduce
В обратном вызове мы выполняем проверки и проверки, требуемые спецификацией API, в соответствии с предоставленной конфигурацией. В этом примере мы не разрешаем пустые URL-адреса и размещать запросы без предоставления данных. Эти проверки могут быть расширены и изменены, но важно то, что мы можем сосредоточиться только на этом одном месте.
reduce
выполняется только при первом вызове API, после чего весьreduce
обработать,get
Будет выполнено только поведение по умолчанию, и будет возвращено значение свойства, которое является обработчиком API. Каждый обработчик возвращает объект Promise, отвечающий за создание запроса и вызов службы.
использовать:
api.get({
url: 'my-url'
}).then((xhr) => {
alert('Success');
}, (xhr) => {
alert('Fail');
});
delete api.get; //throw new Error('API methods cannot be deleted!');
В заключение
Прокси могут пригодиться, когда вам нужен больший контроль над вашими данными. Вы можете расширить или запретить доступ к необработанным данным на основе контролируемых правил для мониторинга объектов и обеспечения правильного поведения.
Если вам понравилась эта статья, подпишитесь на мой официальный аккаунт. Не стесняйтесь выражать свои мысли в разделе комментариев ниже.
Спасибо за вашу готовность потратить свое драгоценное время на чтение этой статьи. Если эта статья дала вам небольшую помощь или вдохновение, пожалуйста, не скупитесь на лайки и звезды. Вы, безусловно, самая большая движущая сила для меня, чтобы двигаться вперед .GitHub.com/Иветт Л.А. Ю/Б…