异步功能'后清理'

时间:2014-06-07 16:44:56

标签: javascript asynchronous

我有这样的设置:我正在尝试使用自定义事件处理程序来处理.data哈希并在处理程序运行后“垃圾收集”它的项目,以避免将它们不必要地保留在内存中,等等.defer()函数模拟我得到的函数,它根据提供的异步运行函数生成函数,尝试模仿本机事件处理方式......

令我困惑的是,在调用延迟函数之后,通过分配... = null;删除数据项似乎在函数执行之前运行,基本上反转执行顺序(?!),留下一个没有数据可用的函数。 ..

这是我的脚本:

  //
  //
  var defer = function(func) {

    // get asynchronoused `.func()` version
    return function() {

      // cache inputs for use by defered function
      var args = arguments;
      var node = this;

      return setTimeout(
        function() {
          func.apply(node, args);
        }
      ), node;

    };
  };


  var action = function(node) {
    // process a node
    console.log(node['@foo']['txt']);
  };


  var data = {

    '@foo': {
      'id'  : '#foo',
      'tag' : 'h2',
      'txt' : 'stuff',
    },

    '@spam': {
      'id'  : '#spam',
      'tag' : 'h1',
      'txt' : 'and shit',
    },
  };

  // run `.action()` asynchronously
  defer(action)(data);

  // garbage collect after
  data['@foo'] = null;
  // this part seems to run before function call
  // cleaning the data before `defer(action)(data);` gets it's time
  // it throws error here because `null` gc-ed it right away (or something)
  //   TypeError: node['@foo'] is null
  // 

<小时/> 我目前正在解决这个问题,通过提供额外的函数(_finaly())来回调,这些回调将在数据处理后立即运行清理,这对于简单的事情来说似乎很尴尬和不自然。问题是为什么片段代码似乎无法正常运行,这里到底发生了什么,或者是否有更清洁的方法来解决问题

这是我到目前为止的解决方案:

  var action = function(node, _finaly) {
    // provide `._finaly()` callback 
    // that will run after processing gets done
    /////

    console.log(node['@foo']['txt']);

    // .. and run the cleanup code
    _finaly && _finaly(node, 'txt');

  };

  defer(action)(data, function (node, item) {
    // do the house-keep in a callback here
    // rather than directly after execution
    node.hasOwnProperty(item) && (node[item] = null);
  });
  //
  // eof

1 个答案:

答案 0 :(得分:1)

因此,正如Bergi所说,你观察到的行为是预期的。在任何异步调用开始之前,主调用堆栈总是完成。如果您对defer的呼叫超过1次,您甚至不知道哪一个会先执行。

为什么不在action函数调用中清理数组?我知道它可能打破了实施的逻辑,并不总是可行的。如果是这样,您可能希望使用本机事件。例如,在这种情况下使用MutationObserver可能是一个有趣的想法。

  1. 观察您选择的隐藏DOMElement
  2. 当您完成并想要使指针无效时,请更改元素的属性
  3. 使用mutations.forEach(function(mutation)抓取变异并使阵列无效。
  4. 但无论如何,我认为你不应该试图“猜测”什么时候取消指针。根据定义,调用异步函数意味着您不知道何时完成。

    希望有所帮助