代码之家  ›  专栏  ›  技术社区  ›  Hatted Rooster

如何总是在函数结束时运行清理?

  •  1
  • Hatted Rooster  · 技术社区  · 7 年前

    假设我有这个函数(psuedo代码):

    function Foo() {
    
      let varThatRequiresCleanup = //something
    
      if(condition1) {
        return Error1;
      }
    
      if(condition2) {
        return Error2;
      }
    
      if(condition3) {
        return Error3;
      }
      //etc.. more ifs and important code.
    
      varThatRequiresCleanup.CleanUp();
      return Success;
    }
    

    goto 但JavaScript两者都没有。

    我该怎么打电话 CleanUp() 无论何时 Foo() 退货?

    清理() if 我回来了?

    5 回复  |  直到 7 年前
        1
  •  2
  •   Dacre Denny    7 年前

    通过这种方式,您可以通过以下方式实现所需:

    function Foo() {
    
      let varThatRequiresCleanup = //something
    
      // Define your "actual" Foo logic in an inner function
      // where you can define your flow and return logic as 
      // needed.
      function InnerFoo() {
    
        // You can access variables in the Foo closure, like so
        console.log(varThatRequiresCleanup);
    
        if(condition1) {
          return Error1;
        }
    
        if(condition2) {
          return Error2;
        }
    
        if(condition3) {
          return Error3;
        }
    
        //etc.. more ifs and important code.
        return Success;
      }
    
      // Now call your inner function like so
      var result = InnerFoo();
    
      // Now you can cleanup resourced in scope of Foo as
      // in this way, because this line will be hit
      varThatRequiresCleanup.CleanUp();
    
      // Return the result from InnerFoo()
      return result;
    }
    
        2
  •  3
  •   Slai    7 年前

    一种替代方法是对重复代码使用函数:

    function Foo() {
    
      let varThatRequiresCleanup = //something
    
      function CleanUpAndReturn(returnValue) {
        varThatRequiresCleanup.CleanUp();
        return returnValue;
      }
    
      if (condition1) { return CleanUpAndReturn(Error1); }
    
      if (condition2) { return CleanUpAndReturn(Error2); }
    
      if (condition3) { return CleanUpAndReturn(Error3); }
      //etc.. more ifs and important code.
    
      return CleanUpAndReturn(Success);
    }
        3
  •  2
  •   Cepheus    7 年前

    可以使用try finally块:

    function Foo() {
      let varThatRequiresCleanup = //something
    
      try {
        if(condition1) {
          return Error1;
        }
    
        if(condition2) {
          return Error2;
        }
    
        if(condition3) {
          return Error3;
        }
        //etc.. more ifs and important code.
    
        return Success;
      } finally {
        varThatRequiresCleanup.CleanUp();
      }
    }
    
        4
  •  1
  •   agDev    7 年前

    你可以做一个叫做猴子补丁的事情。

    概念取自 here .

    function foo(){
        if(condition1) {
            return Error1;
        }
    
        if(condition2) {
            return Error2;
        }
    
        if(condition3) {
            return Error3;
        }
    }
    
    var tempFoo = foo;
    
    window.foo = function() {
        tempFoo();
    
        //do the cleanup here
        CleanUp();
    }
    
        5
  •  0
  •   Get Off My Lawn    7 年前

    它通过返回 new Proxy get

    1. 创建返回新代理的实例
      1. 代理将立即拦截并处理调用
      2. 代理将像以前一样运行函数
      3. 然后代理将运行cleanup函数

    class MyClass {
    
      constructor() {
        this.varThatRequiresCleanup = null
        // Create a reference to `this` so the function below can use it
        let $this = this
        
        // A private function this will clean stuff up
        // We can't use `this` in this function because it references window
        // We will use our reference `$this` instead
        function cleanup() {
          $this.varThatRequiresCleanup = null
          console.log('cleaned up')
        }
    
        // Create a proxy that will handle the method calls
        return new Proxy(this, {
          get: (target, prop, receiver) => {
            // Get the called property
            let targetValue = Reflect.get(target, prop, receiver)
            // Execute the called property
            return (...args) => {
              let r = targetValue.apply(this, args)
              console.log('before varThatRequiresCleanup:', this.varThatRequiresCleanup)
              cleanup()
              console.log('after varThatRequiresCleanup:', this.varThatRequiresCleanup)
              return r
            }
          }
        })
      }
    
      Foo() {
        this.varThatRequiresCleanup = 'foo'
        return 'foo result'
      }
    
      Bar() {
        this.varThatRequiresCleanup = 'bar'
        return 'bar result'
      }
    }
    
    let c = new MyClass()
    console.log('Foo Return Value:', c.Foo())
    console.log('-----------')
    console.log('Bar Return Value:', c.Bar())