NodeJs 回调参数的最佳实践
Best Practice for Callback Parameters in NodeJs
背景
我是 Node.js 中 fast object traversal 的一个低级库的维护者。该库的重点是速度,并且经过了大量优化。然而,有一个很大的放缓:回调参数
问题
回调由图书馆消费者提供,每次扫描可以调用很多次。对于每次调用,都会计算所有参数并将其传递给回调。在大多数情况下,回调实际上只使用了一小部分参数。
目标
目标是消除这些参数的不必要计算。
解决思路
- 理想情况下,NodeJs 会公开回调定义的回调参数。然而,如果没有大量黑魔法(字符串解析),似乎不可能获得它们。它也不会解决仅有条件地需要参数的情况。
- 我们可以要求回调公开所需的参数,而不是尝试从回调中获取参数。这听起来很不方便而且容易出错,而且也不能解决有条件的要求。
- 我们可以为每个参数组合引入不同的回调。这听起来像是个坏主意。
- 我们可以为每个参数传入一个函数来计算和 returns 参数值,而不是直接传入参数。在回调中,参数将根据需要被调用。这很丑陋,但可能是最好的方法?
问题
- 其他图书馆如何解决这个问题?
- 还有什么其他方法可以解决这个问题?
这是一个非常基本的设计决定,我正在努力做到这一点。
非常感谢您的宝贵时间!一如既往的赞赏!
您可以向回调传递一个对象,该对象具有各种方法,使用回调的客户端可以调用这些方法来获取他们实际需要的任何参数。这样,您将拥有一个干净的对象接口,并且您将只计算实际请求的必要信息。
这种通用设计模式有时称为 "lazy computation",您只需根据需要进行计算。您可以使用访问器函数或 getter,具体取决于您要公开的接口类型。
出于性能原因,您或许可以在每次调用回调时重复使用同一个对象,而不是构建一个新对象(取决于您的实现细节)。
请注意,您甚至不必将计算所需的所有信息都放入对象本身,因为在某些情况下,对象上的方法可以在执行操作时引用您自己的本地上下文和本地范围的变量他们的计算。
However there is one big slowdown: Callback Parameters
你真的对这个进行了基准测试吗?我怀疑构建参数值的成本是那么高。请注意,如果这是一个非常频繁使用的调用,V8 可能会内联它,然后优化掉未使用的参数值。
Ideally NodeJs would expose the callback parameters as defined by the callback.
实际上,it does。如果你确实想依赖这个属性,你应该正确地记录你所做的,否则这个魔法可能会导致模糊的错误。
We could introduce a different callback for every parameter combination. This sounds like a bad idea.
提供两个选项 filter(key, value)
和 filterDetailed(key, value, context)
似乎不是什么大问题。如果优化真的值得,而且正如你所说这是一个低级库,那就去吧。
Instead of passing in the parameters directly, we could pass in a function for each parameter that computes and returns the parameter value. Inside the callback the parameter would then be invoked as required. It's ugly but might be the best approach?
构造一个闭包对象来代替参数传递也确实有一些开销,因此您需要正确地对其进行基准测试。这可能不值得。
但是,我看到您实际上传递了一个上下文对象作为参数,在该对象上计算值作为属性进行访问。在这种情况下,您可以简单地使这些属性获取器在访问时计算值,而不是在构造对象时。
背景
我是 Node.js 中 fast object traversal 的一个低级库的维护者。该库的重点是速度,并且经过了大量优化。然而,有一个很大的放缓:回调参数
问题
回调由图书馆消费者提供,每次扫描可以调用很多次。对于每次调用,都会计算所有参数并将其传递给回调。在大多数情况下,回调实际上只使用了一小部分参数。
目标
目标是消除这些参数的不必要计算。
解决思路
- 理想情况下,NodeJs 会公开回调定义的回调参数。然而,如果没有大量黑魔法(字符串解析),似乎不可能获得它们。它也不会解决仅有条件地需要参数的情况。
- 我们可以要求回调公开所需的参数,而不是尝试从回调中获取参数。这听起来很不方便而且容易出错,而且也不能解决有条件的要求。
- 我们可以为每个参数组合引入不同的回调。这听起来像是个坏主意。
- 我们可以为每个参数传入一个函数来计算和 returns 参数值,而不是直接传入参数。在回调中,参数将根据需要被调用。这很丑陋,但可能是最好的方法?
问题
- 其他图书馆如何解决这个问题?
- 还有什么其他方法可以解决这个问题?
这是一个非常基本的设计决定,我正在努力做到这一点。
非常感谢您的宝贵时间!一如既往的赞赏!
您可以向回调传递一个对象,该对象具有各种方法,使用回调的客户端可以调用这些方法来获取他们实际需要的任何参数。这样,您将拥有一个干净的对象接口,并且您将只计算实际请求的必要信息。
这种通用设计模式有时称为 "lazy computation",您只需根据需要进行计算。您可以使用访问器函数或 getter,具体取决于您要公开的接口类型。
出于性能原因,您或许可以在每次调用回调时重复使用同一个对象,而不是构建一个新对象(取决于您的实现细节)。
请注意,您甚至不必将计算所需的所有信息都放入对象本身,因为在某些情况下,对象上的方法可以在执行操作时引用您自己的本地上下文和本地范围的变量他们的计算。
However there is one big slowdown: Callback Parameters
你真的对这个进行了基准测试吗?我怀疑构建参数值的成本是那么高。请注意,如果这是一个非常频繁使用的调用,V8 可能会内联它,然后优化掉未使用的参数值。
Ideally NodeJs would expose the callback parameters as defined by the callback.
实际上,it does。如果你确实想依赖这个属性,你应该正确地记录你所做的,否则这个魔法可能会导致模糊的错误。
We could introduce a different callback for every parameter combination. This sounds like a bad idea.
提供两个选项 filter(key, value)
和 filterDetailed(key, value, context)
似乎不是什么大问题。如果优化真的值得,而且正如你所说这是一个低级库,那就去吧。
Instead of passing in the parameters directly, we could pass in a function for each parameter that computes and returns the parameter value. Inside the callback the parameter would then be invoked as required. It's ugly but might be the best approach?
构造一个闭包对象来代替参数传递也确实有一些开销,因此您需要正确地对其进行基准测试。这可能不值得。
但是,我看到您实际上传递了一个上下文对象作为参数,在该对象上计算值作为属性进行访问。在这种情况下,您可以简单地使这些属性获取器在访问时计算值,而不是在构造对象时。