Expressingx
Expressingx

Reputation: 1572

Send back response one by one in one request?

Is there a way to do 1 request and write every time an response comes? I want to make 1 request and inside to do 10 requests to the db and when an query responses to write on the html? How can i achieve that?

my api

routeHandlers = () => {
    let data: Array<any> = [];
    this._router.get('/api/countdetails/:uid', (req, res) => {
        let uid = req.params.uid;
        console.log(req);
        for (let i = 0; i < 10; i++) {
            data.push({
                id: 'request' + i,
                startTime: performance().toFixed(3)
            });

            let query = `SELECT ${i} AS ID, * FROM CountDetails WHERE UID='${uid}'`;
            this._db.execQuery(query, (err, row) => {
                if (err) throw err;

                for (let i = 0; i < data.length; i++) {
                    Object.keys(data[i]).forEach((val, idx) => {
                        if (val === 'id') {
                            if (data[i][val] === 'request' + row[0]['ID']) {
                                data[i].endTime = performance().toFixed(3);
                                data[i].ellapsed = (performance() - data[i]['startTime']).toFixed(3);
                                res.write('<tr><td>' + data[i]['ellapsed'] + '</td></tr>');

                            }
                        }
                    });
                }

            });

        res.header("Access-Control-Allow-Origin", "*");
        res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        res.end();
        }

    }); 
}

and my html

<div>
    <input type="text" id="iterations" />
    <button type="button" id="btn">send</button>
</div>
<div>
    <table id="tbl">
        <tbody>

        </tbody>
    </table>
</div>

<script>
    var inputValue = document.getElementById('iterations');
    var btn = document.getElementById('btn');
    var array = [];

    btn.addEventListener('click', function () {
        sendRequest(function (xhttp) {
            console.log(xhttp.responseText);
        })
    });

    function sendRequest(callback) {
        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 200) {
               callback(xhttp);
            }
        };
        xhttp.open("GET", "http://localhost:3000/api/countdetails/EAACCDF4-EBC3-4B11-8654-98878BFC4B7B", true);
        xhttp.send({ times: 10});
    }
</script>

Upvotes: 1

Views: 119

Answers (1)

codtex
codtex

Reputation: 6558

First don't use i for nested for.

So you want to call res.end() once all the database calls are finished. This can be done in a variety of ways, but I will give you a quick one with a little tweak of your code. This is the code snippet and the explanations come after: (also read comments in code)

routeHandlers = () => {

    /* 1) we can use the indicator to determine when all the async requests are finished */
    let indicator = 0;
    let data = [];

    this._router.get('/api/countdetails/:uid', (req, res) => {

        /* 2) always set the indicator to 0 on a new request */
        indicator = 0;
        let uid = req.params.uid;

        for (let i = 0; i < 10; i++) {
            data.push({
                id: 'request' + i,
                startTime: performance().toFixed(3)
            });

            let query = `SELECT ${i} AS ID, * FROM CountDetails WHERE UID='${uid}'`;
            this._db.execQuery(query, (err, row) => {
                if (err)
                    throw err;

                for (let j = 0; j < data.length; j++) {
                    Object.keys(data[j]).forEach((val, idx) => {
                        if (val === 'id') {
                            if (data[j][val] === 'request' + row[0]['ID']) {
                                data[j].endTime = performance().toFixed(3);
                                data[j].ellapsed = (performance() - data[j]['startTime']).toFixed(3);
                                res.write('<tr><td>' + data[j]['ellapsed'] + '</td></tr>');
                            }
                        }
                    });
                }

                /* 3) here check if indicator is 10 and if yes then all the database calls should be finished */
                indicator++;
                if (indicator === 10) {
                    res.header("Access-Control-Allow-Origin", "*");
                    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
                    res.end();
                }
            });
        }
    });
}

In short words I will use integer variable as an indicator how many database calls are finished and once number 10 is reached I consider all are done and end the response.

1) Declare indicator variable which will help us to determine when the job is ready;

2) Reset indicator on each coming request (you might also think resetting data)

3) Once database call is finished increment indicator and check its value -> if it is 10 then we are done and end the response.

That's it, short and simple. Let me know if something is unclear.

Upvotes: 1

Related Questions