【问题标题】:Method decorator should return first execution result Typescript方法装饰器应该返回第一个执行结果 Typescript
【发布时间】:2022-01-13 09:07:05
【问题描述】:

我有一个方法装饰器,它只允许执行一次装饰方法。这个函数运行良好,但在我的第三个单元测试中它失败了,因为它给出了未定义但应该返回第一个执行结果。
这是我的装饰器:

import "reflect-metadata";

const metadataKey = Symbol("initialized");

function once(
    target: any,
    propertyKey: string,
    descriptor: PropertyDescriptor
) {
    const method = descriptor.value;
    descriptor.value = function (...args) {
        const initialized = Reflect.getMetadata(
            metadataKey,
            target,
            propertyKey
        );

        if (initialized) {
            return;
        }

        Reflect.defineMetadata(metadataKey, true, target, propertyKey);

        method.apply(this, args);
    };
}  

我认为问题在于 if 语句的返回,它应该返回一些东西但不知道什么。我玩了一点但没有成功,这就是为什么我请求你帮助。
这些是单元测试:

describe('once', () => {
    it('should call method once with single argument', () => {
        class Test {
            data: string;
            @once
            setData(newData: string) {
                this.data = newData;
            }
        }
        const test = new Test();
        test.setData('first string');
        test.setData('second string');
        assert.strictEqual(test.data, 'first string')
    });

    it('should call method once with multiple arguments', () => {
        class Test {
            user: {name: string, age: number};
            @once
            setUser(name: string, age: number) {
                this.user = {name, age};
            }
        }
        const test = new Test();
        test.setUser('John',22);
        test.setUser('Bill',34);
        assert.deepStrictEqual(test.user, {name: 'John', age: 22})
    });

    it('should return always return first execution result', () => {
        class Test {
            @once
            sayHello(name: string) {
                return `Hello ${name}!`;
            }
        }
        const test = new Test();
        test.sayHello('John');
        test.sayHello('Mark');
        assert.strictEqual(test.sayHello('new name'), 'Hello John!')
    })
}); 

提前致谢!

【问题讨论】:

  • 这个装饰器基本上是做memoization的,但是方法调用的结果并没有存储在任何地方。这就是缺少的
  • 但是我该怎么做呢?如果我不知道将调用哪些函数以及将存储多少个值?

标签: javascript typescript decorator


【解决方案1】:

这个装饰器基本上是做memoization的,但是方法调用的结果并没有存储在任何地方。这就是缺少的。

我的建议是添加另一条名为 result 的元数据:

const meta = Reflect.getMetadata(...);

if (meta?.initialized) return meta.result;

const result = method.apply(this, args);
const newMeta = { initialized: true, result };

Reflect.defineMetadata(metadataKey, newMeta, target, propertyKey);

【讨论】:

  • 无法读取属性“已初始化”未定义的" type="TypeError">
  • 编辑后工作,非常感谢
猜你喜欢
  • 2018-04-02
  • 2020-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多