当使用JS时,有些时候你需要使用setTimeout
函数来强制使一段代码在下一个tick(译者注: 这里认为是JS线程的下一个空闲执行阶段)中执行.如果你正在使用Angular,那么你可能已经非常熟悉这些东西了.
setTimeout
的"hack":
setTimeout(() => {
...Code...
这里的代码将会在下一个tick运行
}, 0);
你可能觉得我疯了,但我讨厌写这样的代码,特别是setTimeout
不是我实际需要的东西.我想让这段东西变得更干净些.那假如我们把setTimeout
函数抽象成一个装饰器呢?
让我们创建一个方法装饰器,并且命名为timeout
来让我们的代码更加清爽:
function timeout( milliseconds: number = 0 ) {
return function( target, key, descriptor ) {
var originalMethod = descriptor.value;
descriptor.value = function (...args) {
setTimeout(() => {
originalMethod.apply(this, args);
}, milliseconds);
};
return descriptor;
}
}
在 TypeScript或Babel中,方法装饰器只是一个可以接受三个参数的函数.
target:
类中的静态构造函数,或类的原型上的实例属性
key:
所要修饰成员的name
descriptor:
该成员的属性描述器.
在我们的例子中,我们同样需要传递给我们的装饰器一个参数(毫秒数,默认被设为0),所以我们需要使用装饰器工厂:
一个装饰器工厂只是一个简单的函数,它能够返回在运行时被装饰器调用的表达式.
下一步,我们能够通过desciptor
的value属性得到原始方法的一个引用.
然后我们覆盖原始值,并且创建一个新的函数,这个函数用setTimeout
包裹了原始值.
现在我们能够这样使用我们的装饰器:
class DemoComponent {
constructor() {}
@timeout()
demoMethod() {
// 这里的代码将会在下一个tick运行
}
// With a number
@timeout(2000)
demoMethod() {
// 这里的代码将会在下一个tick运行
}
}
new DemoComponent().demoMethod();
这下好多了,而且你不得不说这确实看起来更酷😎 .
总结:
你可以将装饰器放入到你的apps中,并且利用它们创建一些强大的东西.装饰器不仅仅为框架或者库而服务,所以多具有一些创造性来开始使用它们吧.你可以在这里查看不同的装饰器.
网友评论