【问题标题】:Send back response one by one in one request?请求一一发回响应?
【发布时间】:2018-05-21 12:20:00
【问题描述】:

有没有办法在每次响应时执行 1 个请求和 write?我想发出 1 个请求并在内部对 db 发出 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>

【问题讨论】:

  • 你的代码有什么问题?您的控制台是否给您任何错误?
  • 问题是我不知道什么时候打电话给res.end(),因为请求是async,而我在每次通话结束之前end
  • this._db.execQuery 来自哪个 npm?
  • @Stamos 是我的类函数,它使用sqlite3 模块发出数据库请求
  • 我建议使用promises,因为它是异步的。您可以将 sqlite3 方法包装到 Promise 中。您可以使用 'reduce' 执行链或与 Promise.all 并行运行。或者,如果您不想使用 Promise,那么您可以使用函数进行递归。

标签: javascript node.js express asynchronous


【解决方案1】:

首先不要将i 用于嵌套的for

所以你想在所有数据库调用完成后调用res.end()。这可以通过多种方式完成,但我会给你一个快速的,稍微调整一下你的代码。这是代码 sn-p,后面是解释:(也阅读代码中的 cmets

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,那么我们就完成并结束响应。

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

【讨论】:

  • 哦.. 看来我需要休息了。简单而有效。谢谢
  • 问题:为什么let indicator = 0;' 在外部范围内?
猜你喜欢
  • 2014-03-12
  • 1970-01-01
  • 2022-01-10
  • 1970-01-01
  • 1970-01-01
  • 2017-04-07
  • 1970-01-01
  • 2011-11-13
  • 1970-01-01
相关资源
最近更新 更多