瀑布式函数得到错误的参数传递

时间:2017-02-02 08:02:48

标签: javascript

我正在尝试对async的瀑布函数进行逆向工程,以便更好地理解它是如何工作的 虽然我提出了以下主要工作的代码,但它有一个我无法解释的奇怪行为:传递给下一个函数的参数似乎在某处丢失,被浏览器中的load事件和节点中的require函数所取代。

我的代码:

const waterfall = (callbacks, callback) => {
  callback = callback || function() {
    };

  let counter      = 0,
      errors       = [],
      results      = [],
      nextExecutor = (err, res) => {
        let argsArray           = Array.from(arguments),
            error               = (argsArray.length >= 2 && !!argsArray[ 0 ]
                ? argsArray[ 0 ]
                : false
            ),
            result              = (error
                ? argsArray[ 1 ]
                : argsArray[ 0 ]
            ),
            currentIteration    = counter++,
            currentNextExecutor = (counter === callbacks.length
                ? () => {
              }
                : nextExecutor
            );

        if (error !== false) {
          errors.push(error);
        }

        results.push(result);

        callbacks[ currentIteration ].call(
          {},
          currentNextExecutor,
          result
        );

        if (counter === callbacks.length) {
          callback.call(
            {},
            (errors.length > 0
                ? errors[ 0 ]
                : null
            ),
            results
          );
        }
      };

  callbacks[ counter++ ](nextExecutor);
};

waterfall([
  function(next) {
    console.log('hi! this is first.');
    setTimeout(() => {
      next(null, 10);
    }, 200);
  },
  function(next, x) {
    console.log('hi! this is second: ' + x);
    setTimeout(() => {
      next(null, x);
    }, 200);
  },
  function(next, x) {
    console.log('hi! this is third: ' + x);
    x++;
    setTimeout(() => {
      next(null, x);
    }, 200);
  },
  function(next, x) {
    console.log('hi! this is last.');
    setTimeout(() => {
      next(null, x);
    }, 200);
  }
], (error, results) => {
  console.log('Error: ' + JSON.stringify(error));
  console.log('Results: ' + JSON.stringify(results));
});

预期产出:

hi! this is first.
hi! this is second: 10
hi! this is third: 10
hi! this is last.
Error: null
Results: [ 10, 10, 11, 11]

实际输出:

hi! this is first.
hi! this is second: function require(path) { ... }
hi! this is third: function require(path) { ... }
hi! this is last.
Error: {}
Results: [null,null,null]

我不明白哪里出错了 - arguments对象没有传递值的引用。

注意:这不是为了模仿异步源代码,因为我还没有看过它。我想出于学习目的自行解决问题。

2 个答案:

答案 0 :(得分:0)

编辑:

由于箭头函数不绑定自己的arguments变量,因此我使用的是父作用域arguments。其中,最重要的是浏览器中的load事件或节点中的require

原始答案:

解决了这个问题 - 有趣的是,使用箭头功能不能按预期工作,但我不知道为什么。将nextExecutor的声明交换为标准函数(并重构参数处理一下)似乎解决了这个问题。

因此,nextExecutor代码如下所示:

nextExecutor = function(error, result) {
    let currentIteration    = counter++,
        currentNextExecutor = (counter === callbacks.length
            ? function() {}
            : nextExecutor
        );

    if (!!error) {
      errors.push(error);
    }

    results.push(result);

    callbacks[ currentIteration ].call(
      {},
      currentNextExecutor,
      result
    );

    if (counter === callbacks.length) {
      callback.call(
        {},
        (errors.length > 0
            ? errors[ 0 ]
            : null
        ),
        results
      );
    }
  };

  callbacks[ counter++ ](nextExecutor);
};

答案 1 :(得分:0)

那么你的问题就在这里

result = (error
  ? argsArray[ 1 ]
  : argsArray[ 0 ]
),

由于错误始终为false,因此结果为args [0],它始终为null?

argsArray [索引]换句话说就是......