Как всегда запускать очистку в конце функции?

1

Скажем, у меня есть эта функция (psuedo-code):

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;
}

Исходя из мира C++ и C, я бы просто выполнил очистку в деструкторе или использовал goto но JavaScript не имеет ни того, ни другого.

Как я буду обращаться к CleanUp() когда возвращается Foo()?

Является единственным методом вызова CleanUp() в каждом, if я вернусь?

  • 0
    зацените этот ответ: stackoverflow.com/a/42335949/5549391
  • 0
    Это зависит от того, чего вы пытаетесь достичь. Что это за переменная и почему она требует очистки? Он находится в области действия функции и будет собирать мусор.
Теги:

5 ответов

2
Лучший ответ

В javascript вы можете определять и вызывать функции в функциях (т.е. В закрытии).

Таким образом, вы можете достичь того, что вам нужно, таким образом:

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;
}
  • 0
    Кодекс не будет действовать так же .... Это всегда будет Success
  • 0
    @epascarello Ах, ошибка редактирования - только исправленный ответ. Спасибо за ответ!
Показать ещё 2 комментария
3

Одним из вариантов может быть использование функции для повторяющегося кода:

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);
}
1

Вы можете использовать блок 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();
  }
}
1

Вы можете сделать что-то, называемое патчем обезьяны.

Концепция взята отсюда.

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();
}
0

Вы можете использовать прокси, чтобы перехватывать вызовы к вашим методам.

Он работает, возвращая new Proxy конструктору. Затем мы обрабатываем вызовы get, и с этим мы можем сначала вызвать метод, а затем запустить очистку после этого. Это позволит нам только вызывать очистку один раз внутри прокси-сервера, а не внутри самого метода.

  1. Создать экземпляр, который возвращает новый прокси-сервер
  2. Вызовите один из методов
    1. Прокси-сервер перехватит и обработает вызов сейчас
    2. Прокси-сервер будет выполнять эту функцию, как это было бы
    3. Затем прокси-сервер запустит функцию очистки
    4. Затем прокси-сервер вернет результат с шага 2

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())

Ещё вопросы

Сообщество Overcoder
Наверх
Меню