设计模式:只执行一次的函数(续)

Posted yangzhou33

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式:只执行一次的函数(续)相关的知识,希望对你有一定的参考价值。

概述

最近最近做项目的时候总会思考一些大的应用设计模式相关的问题,我把自己的思考记录下来,供以后开发时参考,相信对其他人也有用。

闭包之殇

本来上篇写的好好地,看起来逻辑也很清晰,但是实际用起来发现了一个巨大的坑。那就是,闭包中的变量将会共享!!!

// utils.js
export function runOnce(func) 
  let runOnce = true;
  return function(params) 
    if (runOnce) 
      func.apply(this, params);
      runOnce = false;
    
  ;

上面的runOnce函数中的runOnce变量,将会被所有调用的函数共享。这就意味着,如果runOnce被用在多个地方,它也只会被执行一次。实例如下:

// utils.js
export function runOnce(func) 
  let runOnce = true;
  return function(params) 
    if (runOnce) 
      func.apply(this, params);
      runOnce = false;
    
  ;


//example.vue
import  runOnce  from '@/utils';
<script>
export default 
  methods: 
    func1RunOnce: runOnce(function h() 
      console.log('hello world1', this);
    ),
    func2RunOnce: runOnce(function h() 
      console.log('hello world2', this);
    ),
  ,
;
</script>

对于上面的例子,我们本意是让func1RunOnce和func2RunOnce各自执行一次,后面就不执行了。但是实际情况是,在func1RunOnce执行之后就把闭包中的runOnce赋值为false了,所以func2RunOnce其实一次也不会执行!!!

所以我们最终走进了一个死胡同,这条路走不通。(暂时不讨论闭包中的变量是一个字典的情况)

起因之throttle

其实整个事件的起因,是模仿了throttle的用法:

//example.vue
import  throttle  from 'debounce-throttle';
<script>
export default 
  methods: 
    funcThrottle: throttle(function h() 
      console.log('hello world1', this);
    , 300),
  ,
;

上面的funcThrottle函数,在300ms内只会执行一次。那么它为什么能够正常执行呢?

通过翻看源代码,我找出了如下原因:

  1. throttle用的变量是timeoutId,每次由timeout生成,各不相同。
  2. 300ms很短,不会有2个同样使用throttle的不同函数,在300内执行。

学到了什么

  1. 目前来看,执行性一次的函数的实现没有最优雅的方法,要么用闭包+字典,要么老老实实在vue实例中加一个变量标记。建议用变量标记。
  2. 慎用闭包。

以上是关于设计模式:只执行一次的函数(续)的主要内容,如果未能解决你的问题,请参考以下文章

js中setInterval()函数只执行一次的原因

C++ 单例模式续

078-只被执行一次的函数

关于setInterval只执行一次的原因

关于setInterval只执行一次的原因

GCD的相关函数使用