我可以通过只运行一次 reducer 来优化我的 Javascript 类,但保留所需的功能吗?

Can i optimize my Javascript class by only running reducer once, but keep the desired functionality?

提问人:johann1301s 提问时间:7/2/2023 最后编辑:johann1301s 更新时间:7/2/2023 访问量:49

问:

注意:在使用 react、redux、react-redux、redux-saga、redux-thunk、有和没有打字稿之后,我正在尝试为前端异步逻辑创建一个新的、更好的框架,具有 redux-saga(没有 redux-saga)和出色的打字稿支持。我已经做了一个很有前途的 MVP,但我还没有弄清楚 redux-saga 的功能。这是以下问题的背景。takeLatest

我的问题,是一个表演的主题。

我创建了一个名为 and a example 说明如何使用它。Actions

class Actions {
    constructor() {
        const actionNames = ['alpha', 'bravo', 'charlie', 'delta', 'echo', 'foxtrot', 'golf', 'hotel', 'india', 'juliet', 'kilo', 'lima', 'mike', 'november', 'oscar', 'papa', 'quebec', 'romeo', 'sierra', 'tango', 'uniform', 'victor', 'whiskey', 'x-ray', 'yankee', 'zulu'];
        this.handler = (action) => console.log(`${action} was just executed.`)
        Object.assign(this, {
            cancel: () => {
                this.handler = (cur) => console.log('Sorry, all actions are «cancelled».')
            },
            actions: actionNames.reduce((acc, cur) => ({
                ...acc,
                [cur]: () => this.handler(cur)
            }), {})
        })
        console.log('The reduce function was just executed!')
    }
}

const {actions: actionsA, cancel: cancelA} = new Actions() // output: The reduce function was just executed!

actionsA.alpha()    // output: alpha was just executed.
actionsA.foxtrot()  // output: foxtrot was just executed.

cancelA()

actionsA.alpha()    // output: Sorry, all actions are «cancelled».
actionsA.foxtrot()  // output: Sorry, all actions are «cancelled».

const {actions: actionsB, cancel: cancelB} = new Actions() // output: The reduce function was just executed!

actionsB.alpha()    // output: alpha was just executed.
actionsB.foxtrot()  // output: foxtrot was just executed.

cancelB()

actionsB.alpha()    // output: Sorry, all actions are «cancelled».
actionsB.foxtrot()  // output: Sorry, all actions are «cancelled».

您可以运行添加的代码片段来验证输出。

问题来了!

是否有可能 - 以某种方式 - 避免在每次创建新实例时都运行 reducer?我知道这将涉及更改 的实现,但我非常希望实例的行为与上面的代码片段和示例中指定的一样。ActionsActions

我的想法是,这可能是可能的,并且将是一个很好的优化,因为考虑到前端应用程序的性质,这将被调用很多次。new Actions()

我会尝试创建一个包装函数/闭包/工厂/生成器或生成该类的包装类。有关我目前正在尝试的示例,请参阅下面的示例。Actions

class ActionsGenerator {
    constructor() {
        const actionNames = ['alpha', 'bravo', 'charlie', 'delta', 'echo', 'foxtrot', 'golf', 'hotel', 'india', 'juliet', 'kilo', 'lima', 'mike', 'november', 'oscar', 'papa', 'quebec', 'romeo', 'sierra', 'tango', 'uniform', 'victor', 'whiskey', 'x-ray', 'yankee', 'zulu'];
        this.handler = (action) => {}
        const actions = actionNames.reduce((acc, cur) => ({
            ...acc,
            [cur]: () => this.handler(cur)
        }), {})
        console.log('The reduce function was just executed in generator!')
        Object.assign(this, {
            Actions: class Actions {
                constructor() {
                    // somehow implement the already created actions here. Is that possible?
                }
            }
        })
    }
}

const { Actions } = new ActionsGenerator()  // output: The reduce function was just executed in generator!

const {actions: actionsA, cancel: cancelA} = new Actions() // <-- No output this time!

...

我希望我想要的程序的输出也会发生变化。

  1. reduce函数刚刚在生成器中执行!
  2. 阿尔法刚刚被处决。
  3. 狐步舞刚刚被处决。
  4. 对不起,所有操作都被«取消»。
  5. 对不起,所有操作都被«取消»。
  6. 阿尔法刚刚被处决。
  7. 狐步舞刚刚被处决。
  8. 对不起,所有操作都被«取消»。
  9. 对不起,所有操作都被«取消»。

如果有人碰巧确定这是不可能的,我将不胜感激。

这可能吗?

谢谢:)

JavaScript 代理 闭包 pass-by-reference reduce

评论


答:

0赞 trincot 7/2/2023 #1

您可以使用代理作为属性的值。这样,您就不必构造(可能很大)对象。相反,代理层将在读取特定操作时返回正确的函数。actions

不是必需的,但我不会覆盖处理程序,而是使用一个属性,处理程序将使用它来决定要做什么。cancelled

class Actions {
    static #actionNames = new Set(['alpha', 'bravo', 'charlie', 'delta', 'echo', 'foxtrot', 'golf', 'hotel', 'india', 'juliet', 'kilo', 'lima', 'mike', 'november', 'oscar', 'papa', 'quebec', 'romeo', 'sierra', 'tango', 'uniform', 'victor', 'whiskey', 'x-ray', 'yankee', 'zulu']);
    
    #cancelled = false;
    actions = new Proxy(this, {
        get(obj, action) {
            if (Actions.#actionNames.has(action)) return () => obj.handler(action);
        }
    })
    
    constructor() {
        this.cancel = () => this.#cancelled = true;
    }
    
    handler(action) {
        if (this.#cancelled) {
            console.log('Sorry, all actions are «cancelled».');
        } else {
            console.log(`${action} was just executed.`);
        }
    }
}

const {actions: actionsA, cancel: cancelA} = new Actions();

actionsA.alpha();    // output: alpha was just executed.
actionsA.foxtrot();  // output: foxtrot was just executed.

cancelA();

actionsA.alpha();    // output: Sorry, all actions are «cancelled».
actionsA.foxtrot();  // output: Sorry, all actions are «cancelled».

const {actions: actionsB, cancel: cancelB} = new Actions();

actionsB.alpha();    // output: alpha was just executed.
actionsB.foxtrot();  // output: foxtrot was just executed.

cancelB();

actionsB.alpha();    // output: Sorry, all actions are «cancelled».
actionsB.foxtrot();  // output: Sorry, all actions are «cancelled».

评论

0赞 johann1301s 7/2/2023
凉!我不知道代理!它似乎也更具有性能,用 和 进行测量。从我读到的关于代理的一点点来看,似乎可以使用陷阱而不是......?console.timeconsole.timeEndapplyget
0赞 trincot 7/2/2023
当调用方读取操作属性时,需要将陷阱放在返回的对象上。因此,您还需要更深地返回代理。这不会带来任何好处。apply