javascript - 在一个请求中一一发回响应?

标签 javascript node.js express asynchronous

有没有办法在每次响应到来时执行 1 个请求并 write ?我想发出 1 个请求并在内部对数据库执行 10 个请求,当查询响应写入 html 时?我怎样才能做到这一点?

我的 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();
        }

    }); 
}

和我的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>

最佳答案

首先不要对嵌套的for使用i

因此,您希望在所有数据库调用完成后调用 res.end()。这可以通过多种方式完成,但我会给你一个快速的方式,对你的代码进行一些调整。这是代码片段,后面是解释:(另请阅读代码中的注释)

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();
                }
            });
        }
    });
}

简而言之,我将使用整数变量作为完成了多少数据库调用的指示器,一旦达到数字 10,我就认为所有操作都已完成并结束响应。

1) 声明indicator 变量,这将帮助我们确定作业何时准备就绪;

2) 在每个即将到来的请求上重置指示器(您可能还想重置 data)

3) 数据库调用完成后,递增 indicator 并检查其值 -> 如果为 10,则我们完成并结束响应。

就是这样,简短而简单。如果有什么不清楚的地方,请告诉我。

关于javascript - 在一个请求中一一发回响应?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47694273/

相关文章:

javascript - 在随机位置定位图像

javascript - 删除 chrome 扩展中的注入(inject)脚本

javascript - 将多个 API 调用合并为一个请求

angularjs - 如何在本地安装 npm 包

javascript - 在 IE8 上执行 windows.open 时无法隐藏状态栏

javascript - 为什么 req.busboy 未定义?

javascript - 为什么要计算回调?

javascript - Mongoose 批量插入遗漏了关键信息

javascript - 来自 Express 的响应未定义且待处理(React 前端)

javascript - 设置为 req 并在另一条路由中访问