node.js 超时重启 api 调用

node.js timeout restarts api call

平台:

我在 sails.js and a frontend in react. The calls between front and back end are being made with fetch api 中有一个 api。

更多信息:

在某些api端点的过程中我必须执行一个外部文件,此时我使用的是execfile() function of node.js,我必须等待它被执行以响应前端。

问题是什么?

如果文件在短时间内执行,例如不到 1 分钟,一切都很好 运行 并且双方都按预期发生行为,但如果(在这种情况下)文件需要更多执行时间超过 1 分钟,有一些东西可以触发对 api 的第二次调用(我不知道这是在哪里调用的,但我用 postman 测试了同一个端点,我没有这个问题所以我怀疑 react / fetch-api) 和 api 调用与第一次调用相同的数据被重做。这会导致文件 运行 两次。

更奇怪的是,如果您打开了 DevTools 网络检查器,则不会出现第二次调用,但 sailjs 的文档中没有任何内容指向此行为。

sails.js中的端点示例:

/**
 * FooController
 */
const execFile = require("child_process").execFile;
module.exports = {
  foo: async (req, res) => {
    let result = await module.exports._executeScript(req.body).catch(() => {
      res.status(500).json({ error: "something has occurred" });
    });
    res.json(result);
  },
  _executeScript: body => {
    return new Promise((resolve, reject) => {
      let args = [process.cwd() + "/scripts/" + "myExternalFile.js", body];
      let elem = await module.exports
        ._execScript(args)
        .catch(err => reject(err));
      resolve(elem);
    });
  },
  _execScript: args => {
    return new Promise((resolve, reject) => {
      try {
        execFile("node", args, { timeout: 150000 }, (error, stdout, stderr) => {
          if (error || (stderr != null && stderr !== "")) {
            console.error(error);
          } else {
            console.log(stdout);
          }
          let output = { stdout: stdout, stderr: stderr };
          resolve(output);
        });
      } catch (err) {
        reject(err);
      }
    });
  }
};

组件对获取调用的反应示例:

import React from "react";
import { notification } from "antd";
import "./../App.css";
import Oauth from "./../helper/Oauth";
import Config from "./../config.json";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      syncInAction: false,
      data: null
    };
  }
  componentDidMount() {
    this.handleSync();
  }
  async handleSync() {
    let response = await fetch(Config.apiLink + "/foo/foo", {
      method: "POST",
      mode: "cors",
      headers: {
        Authorization: Oauth.isLoggedIn(),
        Accept: "application/json",
        "Content-Type": "application/json"
      },
      body: JSON.stringify(this.state.myData)
    }).catch(err => {
      notification.error({
        key: "catch-ApiFail",
        message: "Erro"
      });
    });

    let json = await response.json();
    this.setState({
      syncInAction: false,
      data: json
    });
  }
  render() {
    return <div>{this.state.data}</div>;
  }
}

export default App;

我的预期目标/行为是什么:

无论调用1分钟还是10小时都无所谓,文件只能调用一次,调用完成后,可以return到前端。

请注意,示例没有原始代码,也没有经过测试。是解释行为的代码的简化版本

我最终解决了这个问题,显然 nodejs has a default timing of 2 minutes 在服务器上,并且可以重写以忽略此超时或增加它。 这只是在 foo() 端点的开头添加一行代码,问题就解决了。

重做调用的行为是没有文档记录的,使用postman时没有这个行为很奇怪,但是这里有谁需要的解决方法。

最终结果:

foo: async (req, res) => {
  req.setTimeout(0);
  let result = await module.exports._executeScript(req.body).catch(() => {
    res.status(500).json({ error: "something has occurred" });
  });
  res.json(result);
};