Многие объектно-ориентированные языки имеютДекораторФункции, изменяющие поведение класса. В настоящее время этот метод внедренES7, но ни популярные браузеры, ни Node.js не особенно дружелюбны к нему.
Итак, для использования в проектеDecorator
Если вам нужно использоватьBabelПереведите или используйте расширенный набор JavascriptTypescriptразвивать.
Если вы мало знаете о деталях этой грамматики, вы можете продвинуть этот портал: http://es6.ruanyifeng.com/#docs/decorator, и узнать о его особенностях у господина Жуана Ифэна.
первоначальное намерение
использоватьдекораторПервоначальное намерение состоит в том, чтобы сделать что-то лучше, не изменяя исходный интерфейс. подобно:
- Мобильный телефон можно использовать, но его можно предотвратить, добавив чехол для мобильного телефона;
- В кресле можно сидеть, но удобнее сидеть на подушке;
- Винтовка может стрелять, но она может стрелять точнее с добавлением оптического прицела;
- ......
Если вы хотите понять это более абстрактно, в области компьютеров его можно применять для сбора журналов, перехвата ошибок, проверки безопасности, кэширования, отладки, сохранения и т. д.
Обычно используемые декораторы
Обычно используемые декораторы обычнодекоратор классаа такжедекоратор метода, конечно будетдекоратор недвижимости, но обсуждать особо нечего.
декоратор класса
В основном используется для конструкторов классов, аргументы которых являются конструктором класса:
function testable(target) {
target.prototype.isTestable = true
}
@testable
class MyTestableClass {}
let obj = new MyTestableClass()
obj.isTestable // true
Уведомление:здесьtarget
Если вы добавите метод непосредственно к параметру, вы получите статический метод, который эквивалентенclass
добавить перед методомstatic
ключевое слово; если вы хотите добавить атрибуты экземпляра, вы можете передать целевому классуprototype
манипулирование объектами.
Теперь мы используемдекоратор классаРеализуйте декоратор, который фиксирует время выполнения метода:
const sleepTimeClass = (timeHandler?: (time?: number) => void) => (target: any) => {
Object.getOwnPropertyNames(target.prototype).forEach(key => {
const func = target.prototype[key]
target.prototype[key] = async (...args: any[]) => {
const startTime = await +new Date()
await func.apply(this, args)
const endTime = await +new Date()
timeHandler && await timeHandler(endTime - startTime)
}
})
return target
}
Причина, по которой слой функций также обернут, заключается в том, чтобы позволить пользователям дополнительно обрабатывать полученное время выполнения посредством каррирования:
const sleepTimeClassTimer = sleepTimeClass(time => {
console.log('执行时间', `${time}ms`)
})
@sleepTimeClassTimer
class homepageController {
async get(ctx: any) {
ctx.response.body = await pageService.homeHtml('/page/helloworld', '/page/404')
}
}
Таким образом каждый разclass
После выполнения метода in будет распечатано соответствующее время выполнения.
декоратор метода
function readonly(target, name, descriptor){
// descriptor对象原来的值如下
// {
// value: specifiedFunction,
// enumerable: false,
// configurable: true,
// writable: true
// }
descriptor.writable = false
return descriptor
}
readonly(Person.prototype, 'name', descriptor)
// 类似于
Object.defineProperty(Person.prototype, 'name', descriptor)
Поскольку в асинхронном программированииasync
а такжеawait
Исключение трудно поймать, если принудительноtry...catch
Сделаем, улов бесконечный, код все равно выглядит некрасиво, использовать декоратор очень просто:
const asyncMethod = (errorHandler?: (error?: Error) => void) => (...args: any[]) => {
const func = args[2].value
return {
get() {
return (...args: any[]) => {
return Promise.resolve(func.apply(this, args)).catch(error => {
errorHandler && errorHandler(error)
})
}
},
set(newValue: any) {
return newValue
}
}
}
Затем используйте декоратор метода:
const errorAsyncMethod = asyncMethod(error => {
console.error('错误警告', error)
})
class homepageController {
@errorAsyncMethod async get(ctx: any) {
ctx.response.body = await pageService.homeHtml('/page/helloworld', '/page/404')
}
}
Порядок загрузки декоратора
У класса или метода может быть много вложенных декораторов, поэтому также важно знать порядок их выполнения:
- При наличии нескольких декораторов параметров они выполняются последовательно, начиная с последнего параметра;
- Сначала выполняется декоратор параметров в методе и параметрах метода;
- Декораторы класса всегда выполняются последними;
- Декораторы методов и свойств, кто придет первым, тот и выполнится первым;
- Поскольку параметр является частью метода, он всегда будет выполняться рядом с методом.
Применение декораторов
Это уже было упомянуто в первоначальном замысле.Попробуйте представить, что ему нужно всего несколько декораторов, чтобы завершить базовую производительность и лог-мониторинг фронтенда и бэкенда.Разве это не интересно?