如何处理函数数组中的重复函数调用?

时间:2019-06-10 04:39:40

标签: javascript

我试图按顺序执行函数(sync / async)的以下数组(避免callbackHell),实现函数tf.cond(我需要实现自己的函数以了解回调的工作原理并避免使用Async.js)。

这是我到目前为止所拥有的。函数runCallbacksInSequence运作良好,直到多次获得相同的runCallbacksInSequence为止。它停止并且不再继续执行下一个回调。理想情况下,如果它多次获得相同的callback,则不应第二次执行它,而继续下一个callback

如果您有任何想法,请告诉我我做错了什么以及如何解决。 -没有承诺和异步/等待

callback

3 个答案:

答案 0 :(得分:2)

您的函数链接取决于对k()的调用。因此,在您的缓存逻辑中:

if (cache[f]) {
    return;
} else {
    // ...

链条断裂。

您要的是这个:

if (cache[f]) {
    return k();
} else {
    // ...

替代实现

嵌套函数实现的问题之一是,由于存在多个嵌套作用域(并且多个函数被同时处理(rf,{{1} },k

更简单的方法不是尝试以编程方式构建回调地狱,而是​​可以使用队列(async.js就是这样做的)。这个想法很简单,可以从数组开始直到数组为空的pop()或shift()函数:

cb

如您所见,使用这种结构很容易实现任何流逻辑。通过控制跟踪结果的方式以及每次迭代从数组中删除多少个函数,我们可以轻松实现诸如Waterfall,parallelLimit等功能。

答案 1 :(得分:1)

我想在基于缓存的实现中,您可以通过直接wsimport -keep -p com.samlpe.jaxws.client -extension <WSDL URL> 调用来省略加倍的步骤。

k()

想法:

return;
if (cache[f]) {
  return;
  // f(function(e, x) {
  //   e ? cb(e) : k(x);
  // });

答案 2 :(得分:1)

您的代码对我来说有点难读。所以这是替代解决方案:

<script>
  // The data

  function first(cb) {
    setTimeout(function () {
      console.log('first()');
      cb(null, 'one');
    }, 0);
  }

  function second(cb) {
    setTimeout(function () {
      console.log('second()');
      cb(null, 'two');
    }, 100);
  }

  function third(cb) {
    setTimeout(function () {
      console.log('third()');
      cb(null, 'three');
    }, 0);
  }

  function last(cb) {
    console.log('last()');
    cb(null, 'lastCall');
  }

  const fns = [first, second, third, second, last];

  // We need hash function to create the identifyer of the function
  function hashCode(str) {
    return Array
      .from(str)
      .reduce((s, c) => Math.imul(31, s) + c.charCodeAt(0) | 0, 0);
  }
  const cache = [];

  function reducer(accumulator, currentFunction) {
    // Take the functon string representation to detect "the same function"
    const hash = hashCode(currentFunction.toString());
    // Process the result of the current function and call the next one.
    // We use "reduceRight" so `accumulator` is the next function in the chain.
    const cb = function (fp, result) {
      console.log(result);
      // Cache the result;
      cache[hash] = result;
      accumulator();
    }
    // Run just a callback if we already have the result of the current function
    return () => cache[hash] ? cb(null, cache[hash]) : currentFunction(cb);
  }

  fns.reduceRight(reducer, () => { })();
</script>

结果:

first()
one
second()
two
third()
three
two
last()
lastCall

如果您根本不想处理缓存的结果,则将对回调的调用替换为直接对累加器的调用。

return () => cache[hash] ? cb(null, cache[hash]) : currentFunction(cb);

替换为:

return () => cache[hash] ? accumulator() : currentFunction(cb);

结果:

first()
one
second()
two
third()
three
last()
lastCall

没有缓存的解决方案

它更干净:

<script>
  // Use the same data as in the example with cache

  function reducer(accumulator, currentFunction) {
    const cb = function (fp, result) {
      console.log(result);
      accumulator();
    }
    return () => currentFunction(cb)
  }

  fns.reduceRight(reducer, () => { })();
</script>

结果:

first()
one
second()
two
third()
three
second()
two
last()
lastCall