简体   繁体   中英

Node.js Express Server - Global Variable Issue

To get this out of the way: I am not really posting a bug in this question!


Issue
I recently found a problem with my Node.js and Express backend code, while making multiple requests from the front end at the same time. Let's assume one of my endpoints looks like this:

var payload, id1, id2, data1, data2

exports.someFunction = async (req, res) => {
    payload = req.body.payload
    id1 = req.params.id1
    id2 = req.query.id2
    try {
        data1 = await fetchData1()
        data2 = await fetchData2()
        return responseHandler.success({ data1, data2 })
    } catch (err) {
        return responseHandler.error(err)
    }
}

async function fetchData1() {
    return new Promise((resolve, reject) => {
        // fetch data from database by accessing
        // payload, id1, id2
        // here
    })
}

The issue I discovered, was that the global variables like payload , id1 , etc. were overwritten while the async functions were executed. (If the next request is made before the first one finished) Thereby some functions were executed with wrong inputs and weird responses emerged.


Solution
My solution then was to move those global variables inside the function, which resulted in a heavy usage of function arguments:

exports.someFunction = async (req, res) => {
    const payload = req.body.payload
    const id1 = req.params.id1
    const id2 = req.query.id2
    try {
        const data1 = await fetchData1(payload, id1, id2)
        const data2 = await fetchData2(payload, id1, id2, data1)
        return responseHandler.success({ data1, data2 })
    } catch (err) {
        return responseHandler.error(err)
    }
}

async function fetchData1(payload, id1, id2) {
    return new Promise((resolve, reject) => {
        // fetch data from database
    })
}

As you can see, the code gets really messy, which actually was the reason I used global variables in the first place.


My actual questions

  • (1) Is it silly to use "global variables" in express routes?
  • (2) Is there a better way of supplying other functions with data, rather than inputting all arguments every single time
  • (3) Is my hypothesis correct, that those "global variables" are overwritten when a new request calls this specific route?

(1) Is it silly to use "global variables" in express routes?

Global variables are indeed considered bad practice in general.

(2) Is there a better way of supplying other functions with data, rather than inputting all arguments every single time

What's wrong with inputing them every single time? The code you show seems perfectly fine to me. It's usually better for readability and testing to have the dependencies of your functions explicit.

(3) Is my hypothesis correct, that those "global variables" are overwritten when a new request calls this specific route?

Yes, javascript is executed synchronously by default, until an async / await block appears. In your example, there is no guarantee that the async block will be resolved before another request is made, which make that code very fragile.

  1. Depends on the usage of the global variables. If you have something that is valid for all requests but might change based on other conditions it makes totally sense to use global variables in my opinion. But for your use case it's absolutely the wrong approach as you already found out.
  2. No. The only alternative would be to pass an object with multiple properties instead of multiple arguments - but basically that's the same.
  3. Yes, since the variables are global and requests are asynchronous the variables will be overwritten each time. Depending on the amount of time your fetchData functions take your handler will use the wrong data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM