如何以允许在调用此功能之前和返回此功能后进行额外记录的方式包装 /装饰 /修改功能?
给定以下代码...
function logger = ??
function doSomething() {
logger("doSomething")
console.log("Middle of doing something")
}
是否可以定义 logger
使以下输出产生以下输出?
"started function doSomething"
"Middle of doing something"
"finished function doSomething"
我已经考虑了以下内容:
-
封装
。dosomething
在打印第一行的另一个函数中,调用dosomething
在传递参数时,然后打印最后一行。 -
做前面提到的同样的事情,但使用装饰剂更漂亮。
-
在
dosomething的末尾发送事件
以通知Logger,并使用异步代码来执行此操作(这是在黑暗中拍摄的,不确定) >
在此期间暗示了我采访可以通过“与堆和呼叫堆栈有关的事物”而进行的采访。
是否有一个解决方案不涉及 dosomething
告诉 logger
完成后?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这就是必须走的路。
使用异步代码仅在您已经具有
dosomething
的异步API时才相关。 。那是装饰者的基本思想。
例子:
更多功能...
您可以添加许多扩展/功能。例如:
decorator
功能,该功能将目标功能和任何数量的装饰器作为参数;中执行一些操作,最后
块That's the way to go.
Using asynchronous code is only relevant when you already have an asynchronous API involved in
doSomething
.That's the basic idea of decorators.
Example:
More features...
There are many extensions/features you can add. For instance:
decorator
function that takes the target function and any number of decorators as arguments;finally
block装饰器处理同步和异步函数
您可以创建一个装饰函数,该功能可以处理同步和异步功能。
在下面的摘要中,
logger
是一种装饰函数,它具有作为参数的功能,并返回处理日志记录的装饰函数。如果输入函数返回
Promise
,则使用 “ rel =“ nofollow noreferrer”> Promise.prototype.finally 。注意:
使用
最后
方法确保即使装饰了异步功能的“ ended” log即使失败了。尝试...捕获
块可确保同一件事,但对于同步函数。处理错误案例的方式不同:
如果要处理错误方案的处理方式与成功方案不同,例如,通过打印错误日志而不是结束日志,请参阅下面的摘要:
成功情景的行为没有改变:
Decorator handling both synchronous and asynchronous functions
You can create a decorator function that handles both synchronous and asynchronous functions.
In the snippet below,
logger
is a decorator function that takes in a function as it's argument and returns a decorated function that handles the logging.If the input function returns a
Promise
, it's handled using Promise.prototype.finally.NOTE:
Using the
finally
method ensures that the "Ended" log is printed even if the async function being decorated fails.The
try...catch
block ensures the same thing but for synchronous functions.Handling error cases differently:
If you want to handle the error scenario differently than the success one, for example by printing an error log instead of the end log, then refer to the snippet below:
There's no change in the behavior of the success scenarios:
我将与 @trincot的解决方案相互补充,并使用异步代码处理。
它可以等到异步任务完成并且包装功能对装饰器一无所知
I'll just complement @trincot's solution with the asynchronous code handling.
It can wait until the async task will be finished and the wrapped function doesn't know anything about the decorator
trincot 和 som shekhar mukherjee and dzianis roi 可以看作是一种特殊的装饰函数的一部分,该功能描述了拦截和更改函数或方法的控制流的良好定义的用例,无论这些函数/方法是否异步。
我更喜欢调用此类函数。它们是自己的方法,在
function.protype
asyncfunction.protype
上分别实现,这允许他们的简单用法,因为一个人不需要过多地考虑如何过多考虑实现异步或非迅速函数/方法的正确包装。一个人只需要通过修改器方法选择正确/预期的用例,例如围绕
, ,“ nofollow noreferrer”>,
,
afterThrowing
,OP的用例是最明显的用例,将其他功能包装在一个给定的功能/方法周围,因此无法重构/重写)。下一个提供的示例代码显示了如何通过修饰符的处理程序功能围绕进行更轻松的代码,以便完全控制
mockedfetch
的调用及其结果是要处理...The approaches and implementations of trincot and Som Shekhar Mukherjee and Dzianis Roi can be seen as a part of a special kind of decorator functions which describe well defined use cases of intercepting and altering either a function's or a method's control flow, regardless of whether these function's/method's are async or not.
I prefer calling such functions "method modifiers". They are methods themself, implemented at
Function.prototype
respectivelyAsyncFunction.prototype
, which allows theirs easy usage, because one does not need to think too much about how to implement the correct wrapping of an async or non-async function/method. One just needs to pick the right/intended use case via a modifier method likearound
,before
,after
,afterThrowing
,afterFinally
.The OP's use case is the most obvious one, wrapping additional functionality around a given function/method which one does not own (hence can not refactor/rewrite). The next provided example code shows how easy one can apply additional code via the
around
modifier's handler function in order to get the full control over how the invocation ofmockedFetch
and its result is going to be handled ...好的,因此在了解C#的垃圾收集器之后,我偶然发现了一些使我想起这个问题的东西。这似乎是解决方案:
contrizationRegistry
基本上观察该功能并在垃圾收集器删除对象后调用回调,在这种情况下,在函数完成执行后的某个时间发生了该对象。这可能是面试官检查我对垃圾收集器的了解的方式,这似乎不是JavaScript中的一个流行主题,如果不查看另一种语言,我永远不会找到这种解决方案。
另外,显然它与记录没有什么关系,这可能是一种登录的不良方法,它记录了函数
dosomething
已经完成了很大的延迟运行,因为它等待垃圾收集器来做他的事情,这就是为什么我们需要setInterval
最后(或任何其他事情以保持过程运行)。Ok so after learning about garbage collectors in C# I stumbled upon something that instantly reminded me of this problem. This appears to be the solution:
FinalizationRegistry
basically observes the function and calls the callback once the garbage collector removes the object, which in this case happens some time after the function finished execution.It was probably the interviewer's way to check my knowledge of the garbage collector, it just doesn't seem like a popular subject in JavaScript, I would never have found this solution if not looking at another language.
Also, apparently it has nothing to do really with logging, and this is probably a bad way to log, it logs that the function
doSomething
has finished running in a big delay since it waits for garbage collector to do his thing, that's why we need thesetInterval
in the end(or any other thing to keep the process running).