首页 > 解决方案 > NodeJS将顺序函数调用转换为函数数组

问题描述

我有一个函数以线性方式回调类中的其他函数。

async runTask() {
    debug('runTask');
    debug(this.taskData);

    try {
      // Short circuit for testing
      if (process.env.TASKTIMER) {
        return setTimeout(() => {
          this.taskComplete();
        }, process.env.TASKTIMER);
      }

      // Setup project folder & Git Clone
      await this.pullPackageWait();

      // Create input and output directory
      await this.mkIODirWait();

      // Store task data as json
      await this.writeTaskDataJSONWait();

      // Download Inputs From Amazon
      await this.downloadInputsWait();

      // Link Input files
      await this.linkInputsWait();

      // Download Resources From Amazon
      await this.downloadResourcesWait();

      // Relax permission on tmp directory
      await this.chmodTaskDir();

      // Destroys the job after timeout
      await this.jobTimeout();

      // Determine Handler
      console.log(this.taskData.handler);
      await this.initHandler();
      await this._handler.startJob();
    } catch (err) {
      this.logger.error(err);
      return this.taskError();
    }

我正在尝试将函数调用转换为this answer之后的函数数组。重构后我的函数如下所示:

 async runTask() {
    debug('runTask');
    debug(this.taskData);

    try {
      // Short circuit for testing
      if (process.env.TASKTIMER) {
        return setTimeout(() => {
          this.taskComplete();
        }, process.env.TASKTIMER);
      }

      let currentFunction = 0;
      const functionsToRun = [
        this.pullPackageWait,
        this.mkIODirWait,
        this.writeTaskDataJSONWait,
        this.downloadInputsWait,
        this.linkInputsWait,
        this.downloadResourcesWait,
        this.chmodTaskDir,
        this.jobTimeout,
      ];

      debug('Before The Loop');
      for (currentFunction; currentFunction < functionsToRun.length; currentFunction++) {
        debug('In The Loop');
        await functionsToRun[currentFunction]();
        console.log('Writing to the file');
        await this.writeState();
      }

      // Determine Handler
      console.log(this.taskData.handler);
      await this.initHandler();
      await this._handler.startJob();
    } catch (err) {
      this.logger.error(err);
      return this.taskError();
    }

使用原始代码,整个程序运行正常,但转换后它似乎在第一次回调时中断。我在转换的某个地方犯了错误吗?

标签: arraysnode.js

解决方案


重构代码中最可能的错误来源是不正确的this绑定。请注意以下事项:

this.foo();

不一样:

let foo = this.foo;
foo();

调用时里面this.foo()thisfoo()thisthis.foo. 当调用内部foo()this值时,foo()将要么是全局对象,要么是undefined全局对象,这取决于您是否启用了严格模式。

有关如何this工作的完整解释,请参阅我对另一个问题的回答:Javascript 中的“this”关键字如何在对象文字中起作用?


TLDR

解决方案是将函数名称存储为字符串:

const functionsToRun = [
    'pullPackageWait',
    'mkIODirWait',
    'writeTaskDataJSONWait',
    'downloadInputsWait',
    'linkInputsWait',
    'downloadResourcesWait',
    'chmodTaskDir',
    'jobTimeout',
];

然后调用每个函数:

await this[functionsToRun[index]]();

.bind()功能:

const functionsToRun = [
    this.pullPackageWait.bind(this),
    this.mkIODirWait.bind(this),
    this.writeTaskDataJSONWait.bind(this),
    this.downloadInputsWait.bind(this),
    this.linkInputsWait.bind(this),
    this.downloadResourcesWait.bind(this),
    this.chmodTaskDir.bind(this),
    this.jobTimeout.bind(this),
];

并以您当前的方式称呼他们:

await functionsToRun[currentFunction]();

推荐阅读