반응형
TypeScript 게터를 메모하는 방법
나는 데코레이터를 사용하여 타입스크립트 게터를 메모하기 위해 다음과 같은 접근법을 사용하고 있지만 더 나은 방법이 있는지 알고 싶다. 나는 npm의 인기 패키지를 다음과 같이 사용하고 있다:
import { memoize } from '@app/decorators/memoize'
export class MyComponent {
@memoize()
private static memoizeEyeSrc(clickCount, maxEyeClickCount, botEyesDir) {
return clickCount < maxEyeClickCount ? botEyesDir + '/bot-eye-tiny.png' : botEyesDir + '/bot-eye-black-tiny.png'
}
get leftEyeSrc() {
return MyComponent.memoizeEyeSrc(this.eyes.left.clickCount, this.maxEyeClickCount, this.botEyesDir)
}
}
메모 장식자는 다음과 같습니다:
// decorated method must be pure
import * as memoizee from 'memoizee'
export const memoize = (): MethodDecorator => {
return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
const func = descriptor.value
descriptor.value = memoizee(func)
return descriptor
}
}
My Component에서 두 개의 별도 기능을 사용하지 않고 대신 TypeScript getter에 데코레이터를 직접 추가할 수 있는 방법이 있습니까?
여기서 고려해야 할 사항 중 하나는 장식된 기능이 순수해야 한다는 것입니다(이 시나리오에서는). 하지만 만약 당신이 이것을 만족시키지 못하는 답을 가지고 있다면 그것을 무시해도 좋습니다. 왜냐하면 나는 이 문제에 접근하는 방법에 일반적인 관심이 있기 때문입니다.
데코레이터는 프로토타입 방법과 게터를 모두 지원하도록 확장할 수 있습니다:
export const memoize = (): MethodDecorator => {
return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
if ('value' in descriptor) {
const func = descriptor.value;
descriptor.value = memoizee(func);
} else if ('get' in descriptor) {
const func = descriptor.get;
descriptor.get = memoizee(func);
}
return descriptor;
}
}
게터에 직접 사용하십시오:
@memoize()
get leftEyeSrc() {
...
}
@estus 답변을 바탕으로, 제가 마침내 생각해 낸 것은 다음과 같습니다:
@memoize(['this.eyes.left.clickCount'])
get leftEyeSrc() {
return this.eyes.left.clickCount < this.maxEyeClickCount ? this.botEyesDir + '/bot-eye-tiny.png' : this.botEyesDir + '/bot-eye-black-tiny.png'
}
메모 장식자는 다음과 같습니다:
// decorated method must be pure when not applied to a getter
import { get } from 'lodash'
import * as memoizee from 'memoizee'
// noinspection JSUnusedGlobalSymbols
const options = {
normalizer(args) {
return args[0]
}
}
const memoizedFuncs = {}
export const memoize = (props: string[] = []): MethodDecorator => {
return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
props = props.map(prop => prop.replace(/^this\./, ''))
if ('value' in descriptor) {
const valueFunc = descriptor.value
descriptor.value = memoizee(valueFunc)
} else if ('get' in descriptor) {
const getFunc = descriptor.get
// args is used here solely for determining the memoize cache - see the options object
memoizedFuncs[propertyKey] = memoizee((args: string[], that) => {
const func = getFunc.bind(that)
return func()
}, options)
descriptor.get = function() {
const args: string[] = props.map(prop => get(this, prop))
return memoizedFuncs[propertyKey](args, this)
}
}
return descriptor
}
}
이를 통해 memoize 캐시에 사용할 속성을 결정하는 문자열 배열을 전달할 수 있습니다(이 경우 1개의 prop - clickCount - 는 변수이고 나머지 2개는 상수입니다).
메모지 옵션은 첫 번째 배열 인수만 메모화 목적으로 사용하도록 지정합니다.
아직도 이 코드가 얼마나 아름다운지 이해하려고 노력 중이야!
반응형
'개발하자' 카테고리의 다른 글
"terraform apply"에서 도커 서버 ping 오류 발생 (0) | 2023.07.15 |
---|---|
VScode가 주피터 노트북을 HTML로 내보내지 못함 - 'jupitter-nbconvert'를 찾을 수 없음 (0) | 2023.07.14 |
Kubernetes yaml 파일로 동적 값을 설정하는 방법 (0) | 2023.07.13 |
TypeScript: 개체가 'null'일 수 있습니다 (0) | 2023.07.12 |
다른 지역에 Terraform 코드 파이프라인 배포 (0) | 2023.07.12 |