首页 > 解决方案 > 事件触发但并非所有代码都被执行

问题描述

我正在 github 上开发一个名为lan-info的项目。
我有以下代码

let arpSweepCommand = './arpSweep.sh';
app.get('/arp', (req, res) => {
  console.log('we have a working signal!');
  executeCommand(arpSweepCommand, req, res, false);
  fs.readFile('command_output/arpedHosts.txt', 'utf-8', (error, data) => {
    if (error) {
      res.send(error);
    } else {
      res.send(data);
    }
  })
})

并且 arpSweep.sh 包含:

timeout 10s netdiscover -P > command_output/arpedHosts.txt

在我的前端我有一个 Jquery AJAX 调用:

arpButton.click(function () {
  loader.show();
  $.ajax({
    method: 'GET',
    url: '/arp',
    success: function (data) {
      console.log(data);
      commandOutput.append(data);
      loader.hide();
    }
  })
})

我知道没有语法错误,因为 webpack 编译前端代码时没有抱怨;而且我知道后端确实捕获了请求,因为每当我单击arpButton它时都会打印“我们有信号!” 在服务器上。
但问题是 loader.show()/hide() 似乎只在这个 ajax 请求中什么都不做我知道这是特定于这个 ajax 请求的,因为我有类似的请求可以完美运行。
对我来说问题是信息不会自动附加到commandOutput.
我需要再次单击arpButton以将输出附加到commandOutput.
但是加载器不会为我显示我知道加载器不会很快出现和消失,因为 ajax 调用至少需要 10 秒才能完成。
另一个问题是我测试了10秒后数据没有自动出现commandOutput,点击后等待30分钟,只有加载器出现故障,arpButton但没有任何反应;当我arpButton再次单击时,输出会立即显示。
那么为什么页面不更新自身呢?相反,它迫使我重新单击该按钮。如果您需要更多信息,可以单击文件上方的项目链接:
src/index.js
index.js
arpSweep.sh
注意:如果 index.js 不是您使用的子网,请务必更改顶部的子网(自动子网检测是我计划稍后实现的功能)。
编辑:在尝试读取文件作为回调后executeCommand

function executeCommand (command, req, res, sendRes = true, callback) {
  exec(command, (error, stdout, stderr) => {
    console.log(`stdout: ${stdout}`)
    console.log(`stderr: ${stderr}`)
    if (error !== null) {
      console.log(`Error ${error}`)
    } else if (sendRes === false) {
    } else if (typeof callback === 'function') {
      callback()
    } else {
      res.send(stdout + stderr)
    }
  })
}
app.get('/arp', (req, res) => {
  console.log('we have a working signal!')
  executeCommand(arpSweepCommand, req, res, false, function () {
    fs.readFile('command_output/arpedHosts.txt', 'utf-8', (error, data) => {
      if (error !== null) {
        res.send(error)
      } else {
        res.send(data)
      }
    })
  })
})

我遇到了一个新问题:现在单击
arpButton加载程序出现但在 10 秒后(在 netdiscover 被杀死之前分配给 arpSweep.sh 中的命令的时间)似乎没有任何区别,加载程序似乎永远停留在那里。
在服务器上我发现了以下错误。

error: Error can't execute command './arpSweep.sh'

标签: javascriptjquerynode.jsexpress

解决方案


我的问题是信息不会自动附加到commandOutput

您遇到的问题是因为浏览器不知道如何append json(我认为它并不总是 json 响应)。尝试追加responseText而不是data

success: function (data, status, xhr) {
  console.log(data)
  commandOutput.append(xhr.responseText + '\r\n')
}

至于加载器 - 一切正常,也许你只需要隐藏它而不是successcomplete回调上。

在这部分:

executeCommand(arpSweepCommand, req, res, false)
fs.readFile('command_output/arpedHosts.txt', 'utf-8', (error, data) => {

您异步调用 executeCommand,因此您无法确定输出是否来自当前调用(当您需要单击两次时,这可能是问题的核心)。因此,您应该在方法内部的回调中移动reading file部分代码,如下所示:execexecuteCommand

function executeCommand (command, req, res, cb) {
  exec(command, (error, stdout, stderr) => {
    console.log(`stdout: ${stdout}`)
    console.log(`stderr: ${stderr}`)
    if (error !== null) {
      console.log(`Error ${error}`)
    } else {
      if (typeof cb === 'function') {
        cb()
      } else {
        res.send(stdout + stderr)
      }
    }
  }
}

executeCommand(arpSweepCommand, req, res, () => {
  fs.readFile('command_output/arpedHosts.txt', 'utf-8', (error, data) => {
    if (error) {
      res.send(error)
    } else {
      res.send(data)
    }
  })
})

推荐阅读