【问题标题】:How to finish the loop to insert data into an array before populating the JSON in nodeJs如何在 nodeJs 中填充 JSON 之前完成循环以将数据插入数组
【发布时间】:2020-11-04 06:26:57
【问题描述】:

我喜欢将循环中的所有数据填充到数组中,但问题是循环最后执行。我尝试打印数据,但数组始终为空。

var data = new Array();
        for (let station of table) {
            request.query('SELECT TOP (1) CONVERT(varchar, Date_Time, 120) Date_Time FROM '+station+' ORDER BY Date_Time DESC', function (err, req) {
                if (err) throw err;
                date_time = req.recordset.map(el=>el.Date_Time)[0];
                var i = data.push({"date_time":date_time,"station_name":name[table.indexOf(station)]});
                console.log(i);
            });
        }
        let json_data = JSON.stringify({"data":data});
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.write(json_data);
        res.end();

【问题讨论】:

    标签: javascript node.js rest express


    【解决方案1】:
    request.query('your query....', callback(err, res))
    

    您的 SQL 查询正在异步运行。因为 SQL 查询是异步的,它们在完成之前立即返回,导致您的循环几乎立即完成,而无需等待任何查询完成。然后,您将在数据更改之前发送数据,因为尚未执行任何完成回调。

    您需要一种方法来强制您的代码等到所有回调完成后再发送结果。

    我发现了一个类似的问题,有一些非常好的解决方案,尤其是第一个答案中的 ES6 标准承诺部分:How can I wait for set of asynchronous callback functions?

    我以该页面为基础来重写您的代码作为示例,因为它可能会变得非常混乱:

    var data = new Array();
    var promises = []; // this will be filled up with Promises, allowing us to wait for them all to complete
    
    // define a function to turn your callback style async requests into awaitable Promises
    function doQuery(yourQuery, station) {
        return new Promise(function(resolve, reject) {
            request.query(yourQuery, function (err, res) {
                if (err) reject(err);
                date_time = res.recordset.map(el=>el.Date_Time)[0];
                var i = data.push({"date_time":date_time,"station_name":name[table.indexOf(station)]});
                console.log(i);
                resolve(res);
            });
        });
    }
    
    // run all of your queries
    for (let station of table) {
    // this will run a query and add it to the Promise array so we can keep track of it and wait for it
        promises.push(doQuery('SELECT TOP (1) CONVERT(varchar, Date_Time, 120) Date_Time FROM '+station+' ORDER BY Date_Time DESC', station));
    }
    
    // Promise.all will pause execution until every Promise in our array is done, then run a callback with the results of everything
    Promise.all(promises).then(function() {
            // complete
            json_data = JSON.stringify({"data":data});
            res.writeHead(200, {'Content-Type': 'text/html'});
            res.write(json_data);
            res.end();
        }, function(err) {
            // error occurred...
            console.log(err);
        }
    );
    

    【讨论】:

      【解决方案2】:

      由于 SQL 查询的异步特性,您必须首先收集所有查询承诺并传递给 Promise.all()。

      Promise.all() 方法将一个可迭代的 Promise 作为输入,并返回一个解析为输入 Promise 结果数组的 Promise。

      我正在使用 async/await 粘贴您的代码示例版本。

        const data = new Array();
        const queriesArray = []
        for (let station of table) {
          const result = await request.query('SELECT TOP (1) CONVERT(varchar, Date_Time, 120) Date_Time FROM ' + station + ' ORDER BY Date_Time DESC')
          queriesArray.push(result)
        }
        Promise.all(queriesArray).then((details) => {
          details.map(detail => {
            date_time = detail.recordset.map(el => el.Date_Time)[0];
            var i = data.push({ "date_time": date_time, "station_name": name[table.indexOf(station)] });
            console.log(i);
          })
          let json_data = JSON.stringify({ "data": data });
          res.writeHead(200, { 'Content-Type': 'text/html' });
          res.write(json_data);
          res.end();
        })
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-09-15
        • 1970-01-01
        • 2018-04-21
        • 2019-09-23
        • 1970-01-01
        • 2017-07-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多