【问题标题】:Connection not closing using http with node.js使用带有 node.js 的 http 连接未关闭
【发布时间】:2021-09-22 04:18:32
【问题描述】:

我在 Node.js 中编写了以下函数,以便从另一台服务器获取 json 数据,以便将其保存在数据库中并进行进一步处理。目前的功能是:

const db = require('../models/db.js')    
const gameHistDB = db.gameHistDB
const gameControlDB = db.gameControlDB
const http = require('http')

const playMove = async (req, res) => {
    try{
        console.log("playing")
        var playOptions = {
            hostname:'115.146.93.216',
            port: 5000,
            path: '/action/a159257a6840135d2edd5a3de3017356/game1/46',
            method: 'GET',
            agent:false,
            Connection:'close'
        }
        console.log(playOptions.path)
        var returnedData;
        var req = http.request(playOptions, res => {
            console.log(res.statusCode)

            let data = ''
            res.on('data',(d) => {
                data += d;
                console.log(d)
            });

            res.on('close',()=>{
                returnedData = JSON.parse(data)
                console.log(returnedData.turninfo.gamestep)
                // gameHistDB.insert(returnedData)
            });

        })

        req.on('error',error => {
            console.error(error)
        })

        req.end()
        console.log('Note that we got here')

    } catch (err) {
        console.log(err)
    }
}

(这可能比它需要的复杂一点,但我想看看到底发生了什么)

当我调用它时,浏览器挂起在“获取数据”模式,并且似乎没有进入它认为所有数据都已处理的状态,尽管它肯定会进入“关闭”块并记录正确的数据。如果我取消注释将请求的 json 插入数据库的代码,那么会发生非常讨厌的事情,不断的 nano 错误告诉我重新验证缓存。

我也不确定在 res.on('close') 中执行数据库查询是否是一个好的工作流程 - 在我正在处理数据库查询的其他函数中,我正在使用 await 来确保查询在执行之前完成其他的东西,但我这里好像做不到。

任何帮助表示赞赏

编辑:与 cmets 一样,我认为可能是另一台机器上的 json 发送代码有问题。那就是:

try{
    console.log("playing")

    ...

    const python = spawn('python3',['./playGameMove.py',JSON.stringify(gamestep),req.params.move]);
    python.stdout.on('data',function(data){
        console.log('Getting data from playGameMove.py');
        nextState.push(data);
    });
    python.on('close',(code) => {
        console.log('in close');
        res.send(nextState.join(""))
    });
}catch(err){
    console.log(err)
}

在 res.send 之后我应该做些什么来确保这段代码知道它已经完成了吗?

【问题讨论】:

  • 可能是一个错字:尝试res.on('end',... 而不是res.on('close',...。我认为没有“关闭”事件。
  • 感谢您的建议。我试过了,“结束”似乎表现出与“关闭”相同的行为
  • 我个人更喜欢使用 axios 库来发出 http 请求
  • @aliland 就我个人而言,我很久以前就停止使用 Axios,遇到了太多问题,我使用了在 Node 中实现浏览器原生 fetchnode-fetch... 效果很好
  • 您在任何其他逻辑触发(res.on('data') 等)之前立即调用req.end()。另外,你有两个res对象(一个是Node提供的,一个是http提供的。有冲突。第二个名字不同,用第一个回复浏览器。你不是回复浏览器,这就是为什么它挂起(res.end(someData)

标签: javascript node.js http asynchronous


【解决方案1】:

您的代码存在三个主要问题。

  1. 您正在命名两个“req”和两个“res”
  2. 执行顺序不是你想的那样。您将在任何事情发生之前立即关闭请求(欢迎来到异步世界)
  3. 您没有回复浏览器,导致浏览器挂起。

以下是有关您当前代码的所有问题的 cmets。 (我已经删除了 try/catch 块,因为它没用,你有 req.on('error') 的错误管理,没有其他应该失败)

const playMove = async (req, res) => { // No need for the "async" keyword. You're not using its counterpart, "await".

    var playOptions = { /* ... */ }
    var returnedData;

    // Problem here, you have called "req" like the other "req" from line 1. Now you have two "req"... Which is which?
    var req = http.request(playOptions, res => { // Executed 1st

        // Problem here, you have called "res" like the other "res" from line 1. Now you have two "res"... Which is which?

        console.log(res.statusCode)  // Executed 5th

        let data = ''
        res.on('data', (d) => {  // Executed 6th
            data += d;
            console.log(d)  // Executed 7th, 7th, 7th, every time there's a data coming in
        });

        res.on('close', () => { // Executed 8th
            returnedData = JSON.parse(data) // Executed 9th
            console.log(returnedData.turninfo.gamestep) // Executed 10th
            // gameHistDB.insert(returnedData)
        });

    })

    req.on('error', error => {  // Executed 2nd
        console.error(error)
    })

    req.end()  // Executed 3rd

    console.log('Note that we got here')  // Executed 4th
}

这是一个更正的版本:

const playMove = (req, res) => {

    var playOptions = { /* ... */ }
    var returnedData;

    var reqHTTP = http.request(playOptions, resHTTP => { // Executed 1st. Using different names to not mix things up.

        console.log(resHTTP.statusCode)  // Executed 4th

        let data = ''
        resHTTP.on('data', (d) => {  // Executed 5th
            data += d;
            console.log(d)  // Executed 6th, 6th, 6th, every time there's a data coming in
        });

        resHTTP.on('close', () => { // Executed 7th
            returnedData = JSON.parse(data) // Executed 8th
            console.log(returnedData.turninfo.gamestep) // Executed 9th
            // gameHistDB.insert(returnedData)
            reqHTTP.end()  // Executed 10th

            res.send(returnedData); // Now reply to the browser! Executed 11th
        });

    })

    req.on('error', error => {  // Executed 2nd
        console.error(error)
    })

    console.log('Note that we got here')  // Executed 3rd
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-23
    • 1970-01-01
    • 2014-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多