Потоковая передача данных из oracle db в браузер с помощью node.js - PullRequest
0 голосов
/ 07 марта 2019

Я изучаю node.js и базу данных.Я пытаюсь передать тяжелые данные о 7 700 000 строк и 96 столбцов от оракула к клиенту.Позже я использую эти данные для виртуальной таблицы.Но в клиенте он показывает только одну строку, а затем в команде узла появляется сообщение об ошибке «Невозможно установить заголовки после их отправки клиенту».Как для потоковой передачи данных в клиенте.Пожалуйста, помогите

var oracledb = require('oracledb');
const cors = require('cors');
var express = require('express');
var app = express();
app.use(cors());

oracledb.outFormat = oracledb.ARRAY;

oracledb.getConnection({
        user: 'user',
        password: 'password',
        connectString: 'some string'
    },
    (err, connection) => {
        if (err) {
            console.error(err.message);
            return;
        }
        var rowsProcessed = 0;
        var startTime = Date.now();
        var dataSize = 0;

        var stream = connection.queryStream(
            'SELECT * FROM table',
        );

        // stream.on('data', function (data) {
    //     rowsProcessed++;
    //     // console.log(JSON.stringify(data));
    //     // console.log(data);

    //     dataSize = dataSize + data.length;
    //     // oracleData.push(data);
    //     // console.log("pushing");
    //     // console.log(oracleData);
    //     // app.get('/data', (req, res) => {
    //     //     res.send(data);
    //     // })
    //     // console.log(data);
    // });

        app.get('/data', (req, res) => {
            stream.on('data', (data) => {
                rowsProcessed++;
                dataSize = dataSize + data.length;
                res.send(JSON.stringify(data));
            })
        })

        stream.on('end', function () {
            var t = ((Date.now() - startTime) / 1000);
            console.log('queryStream(): rows: ' + rowsProcessed +
                ', seconds: ' + t);
            // console.log(dataSize + ' bytes');
            connection.close(
                function (err) {
                    if (err) {
                        console.error(err.message);
                    } else {
                        console.log("connection closed")
                    }
                }
            )
        })

    }
);


app.listen(5000, () => {
    console.log('Listening at 5000')
})

Я пытался использовать вышеупомянутый подход.Но это терпит неудачу.Как мне добиться результата?Браузер зависает, если я вывожу все данные за один раз, поэтому я пытаюсь использовать потоковую передачу, и в командной строке узла он отображает нехватку памяти, если я загружаю все данные за один раз.

Спасибо.

1 Ответ

0 голосов
/ 07 марта 2019

Первое, что вы захотите сделать, это организовать свое приложение немного лучше.Разделение проблем важно, у вас должен быть пул соединений и т. Д. Посмотрите на эту серию для некоторых идей: https://jsao.io/2018/03/creating-a-rest-api-with-node-js-and-oracle-database/

Как только вы выяснили организацию, включите этот пример потоковой передачи большого результатаустановить.

const oracledb = require('oracledb');

async function get(req, res, next) {
  try {
    const conn = await oracledb.getConnection();

    const stream = await conn.queryStream('select * from employees', [], {outFormat: oracledb.OBJECT});

    res.writeHead(200, {'Content-Type': 'application/json'});

    res.write('[');

    stream.on('data', (row) => {
      res.write(JSON.stringify(row));
      res.write(',');
    });

    stream.on('end', () => {
      res.end(']');
    });

    stream.on('close', async () => {
      try {
        await conn.close();
      } catch (err) {
        console.log(err);
      }
    });

    stream.on('error', async (err) => {
      next(err);

      try {
        await conn.close();
      } catch (err) {
        console.log(err);
      }
    });
  } catch (err) {
    next(err);
  }
}

module.exports.get = get;

Если вы обнаружите, что делаете это много, упростите вещи, создав поток многократного преобразования:

const oracledb = require('oracledb');
const { Transform } = require('stream');

class ToJSONArray extends Transform {
  constructor() {
    super({objectMode: true});

    this.push('[');
  }

  _transform (row, encoding, callback) {
    if (this._prevRow) {
      this.push(JSON.stringify(this._prevRow));
      this.push(',');
    }

    this._prevRow = row;

    callback(null);
  }

  _flush (done) {
    if (this._prevRow) {
      this.push(JSON.stringify(this._prevRow));
    }

    this.push(']');

    delete this._prevRow;

    done();
  }
}

async function get(req, res, next) {
  try {
    const toJSONArray = new ToJSONArray();
    const conn = await oracledb.getConnection();

    const stream = await conn.queryStream('select * from employees', [], {outFormat: oracledb.OBJECT});

    res.writeHead(200, {'Content-Type': 'application/json'});

    stream.pipe(toJSONArray).pipe(res);

    stream.on('close', async () => {
      try {
        await conn.close();
      } catch (err) {
        console.log(err);
      }
    });

    stream.on('error', async (err) => {
      next(err);

      try {
        await conn.close();
      } catch (err) {
        console.log(err);
      }
    });
  } catch (err) {
    next(err);
  }
}

module.exports.get = get;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...