Search code examples
javascriptnode.jsaxiosfs

Javascript for loop variable is strange when writing on a file


I have this code in './utils/url.js'. it basically makes the application/x-www-form-urlencoded content form:

const ContentForm = ()=>{
    let params = new URLSearchParams()
    const randomString = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
    params.append('email', `${randomString}@gmail.com`)
    return params;
}
module.exports = ContentForm;

The email parameter is a random string.

and index.js:

const axios = require('axios').default;
const fs = require('fs');
const params = require('./utils/url')

for (let i = 0; i < 1000; i++) {
const config = {
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    }
  }
// sending post with data of web/application the url http://somewhere.com/my-account/
axios.post('http://somewhere.com/my-account/',params(),config, {
})
    .then(function (response) {
         console.log("request successfully made")
    })  
    .catch(function (error) {
        // seeing the error response code
        console.log(error.response.status);
    })
    .finally(function () {
        // always executed
        fs.writeFileSync('./r.txt',String(i));
    })

}

So I want that the 'i' variable be written in the ./r.txt. It actually means that which request we are sending write now. but the problem is that it is really strange in it: look the video of r.txt changes here


Solution

  • You are running 1000 asynchronous operations in a loop. You start them sequentially, but they all run in parallel. Then as each one finishes each one calls fs.writeFileSync() and it's a race to see which one calls it when. It will be random in what order each one finishes, which is what I think your video shows.

    You can sequence them to be in order using await like this:

    const axios = require("axios").default;
    const fs = require("fs");
    const params = require("./utils/url");
    
    async function run() {
    
        for (let i = 0; i < 1000; i++) {
            const config = {
                headers: {
                    "Content-Type": "application/x-www-form-urlencoded",
                },
            };
            // sending post with data of web/appliaction the url http://somewhere.com/my-account/
            await axios
                .post("http://somewhere.com/my-account/", params(), config, {})
                .then(function(response) {
                    console.log("request succesfully made");
                })
                .catch(function(error) {
                    // seeing the error response code
                    console.log(error.response.status);
                })
                .finally(function() {
                    // always executed
                    fs.writeFileSync("./r.txt", String(i));
                });
        }
    }
    
    run().then(() => {
        console.log("done");
    }).catch(err => {
        console.log(err);
    });
    

    Or, reorganized a bit to not mix await and .then() in the same function like this:

    const axios = require("axios").default;
    const fs = require("fs");
    const params = require("./utils/url");
    
    async function run() {
        for (let i = 0; i < 1000; i++) {
            const config = {
                headers: {
                    "Content-Type": "application/x-www-form-urlencoded",
                },
            };
            // sending post with data of web/appliaction the url http://somewhere.com/my-account/
            try {
                let response = await axios.post("http://somewhere.com/my-account/", params(), config, {});
                console.log("request succesfully made");
            } catch(error) {
                console.log(error.response.status, error);
            } finally {
                fs.writeFileSync("./r.txt", String(i));
            }
        }
    }
    
    run().then(() => {
        console.log("done");
    }).catch(err => {
        console.log(err);
    });