How to set the timeout for http requests by nodejs

scenario: do I need to call an interface in nodejs that takes a long time to process? it may take more than 120s.

  nodejs  http 120s,

question:




Koa example:

//  
    const timeoutService = function (time) {
    time = time || 5000
    return new Promise((resolve, reject) => {
        try {
            setTimeout(function () {
                let data = [{
                                name: "Tommy",
                                age: 10
                            }, {
                                name: "Jupiter",
                                age: 18
                            }];
                resolve(data)
            }, time)
        } catch (e) {
            reject(e)
        }
    }).then(res => {
        return res
    }).catch(e => {
        return e
    })
}

router.get("/list", async (ctx) => {
    // 120s
    let data = await timeoutService(121000)
    ctx.status = 200;
    ctx.body = {
        success: true,
        data: data
    };
});

use nodejs to call

// nodejs 
const GetList = (data) => {
  return new Promise((resolve, reject) => {
    let bs = JSON.stringify(data)
    console.log(bs)
    let encode = new Buffer(bs).toString("base64")
    let postData = JSON.stringify({ data: encode})
    var opt = {
        method: "GET",
        host: "localhost",
        port: 3100,
        path: "/list",
        headers: {
            "Content-Type": "application/json",
            "Content-Length": Buffer.byteLength(postData),
            "Accept": "application/json; charset=utf-8"
        }
    }
    let req = http.request(opt)
    req.on("response", (res) => {
        console.log(":" + res.statusCode)
        console.log(": " + JSON.stringify(res.headers))
        let body = ""
        res.on("data", (data) => {
          body += data
        })
        res.on("end", () => {
          resolve(body)
        })
    })

    req.on("error", (e) => {
      console.log(e)
      console.error(":" + e.message)
      reject(e.message)
    })
    req.setNoDelay(0)
    req.write(postData)
    req.end()
  })
}

function getTimeLast(label, startTime) {
    let finishTime = Date.now()
    let last = (finishTime - startTime) / 1000
    console.log(`${label} ${last}`)
}

let startTime = Date.now()
GetList({a: 1}).then(res => {
    console.log(res)
    getTimeLast(":", startTime)
}).catch(e => {
    console.log(e)
    getTimeLast(":", startTime)
}) 

the result is returned as follows:

{"a":1}
{ Error: socket hang up
    at createHangUpError (_http_client.js:331:15)
    at Socket.socketOnEnd (_http_client.js:423:23)
    at emitNone (events.js:111:20)
    at Socket.emit (events.js:208:7)
    at endReadableNT (_stream_readable.js:1055:12)
    at _combinedTickCallback (internal/process/next_tick.js:138:11)
    at process._tickCallback (internal/process/next_tick.js:180:9) code: "ECONNRESET" }
:socket hang up
socket hang up
: 120.018

Mar.25,2021

this problem should be that I did not locate the problem well. I combed it myself.
timeout can be understood as a value of patience, and the client can set its own timeout when sending a request. At the same time, the server also has its own patience value, the two do not interfere with each other, and both have the right to lose the link after the timeout.

  • when the client sends the request, if the server still does not return within the client timeout time, then it will terminate the request.
  • if the client is patient enough (the timeout is big enough), but the intermediate server is not patient, the client will also receive a 504 timeout
  • if the target server does not return after the timeout, the link will also be closed and the client will not receive the return.

so it is possible to use request.setTimeout to set the requested timeout, but this value cannot exceed the maximum limit of the server itself. For example, server.timeout = 5000; even if you set 6000 in setTimeout, it still doesn't work. So if the bottleneck is the timeout limit with the interface server, it is useless to modify the client timeout.


https://www.jb51.net/article/.
this can help you


< del > request.setTimeout < / del >

< del > because there is no response for a long time, the client thinks that the socket has been disconnected, but the server does not think that it allows you to reuse the original socket. < / del >

Menu