Как синхронно загрузить CSV-файл в память перед обработкой HTTP-запросов - PullRequest
3 голосов
/ 28 марта 2019

Я пытаюсь написать простое приложение express / node.js, которое отвечает на GET-запросы, используя данные из файла csv. Я хотел бы прочитать этот csv-файл, чтобы сгенерировать объект javascript (по сути, отображение значения ключа), а затем сделать эту сгенерированную карту доступной для логики обработки HTTP-запросов в контроллере.

Я написал модуль, который читает файлы csv и экспортирует нужные объекты, но я не уверен, как обеспечить:

  1. Эта операция завершается, и объекты фактически существуют до обработки запросов HTTP
  2. Файловая операция выполняется только один раз при запуске сервера, а не один раз за запрос, влекущий за собой огромные накладные расходы

Как мне организовать свой код для достижения этих целей в контексте экспресс-приложения?

Вот как я обрабатываю файл CSV:

var myMap = {};

fs.createReadStream('filename.csv')  
  .pipe(csv())
  .on('data', (row) => {
    // Build javascript object
    myMap[row['key']] = row['value'];
  })
  .on('end', () => {
    console.log('Done.');
  });

// Does this work?
module.exports =  myMap;

Ответы [ 3 ]

1 голос
/ 28 марта 2019

Я бы искал более синхронный способ чтения файла и обработки http-запроса.Вот пример кода того, как он должен выглядеть,

import fs from 'fs';

async function processCSV() {
    try {
        let map = await readCsv();
        //handle http request in another function with same async await way
        let http = await processHttpRequest(map);

        // process  the http response
    } catch (e) {
        console.log('e', e);
    }

}

function readCsv()
{
    let myMap = [];
    fs.createReadStream('filename.csv')
        .pipe(csv())
        .on('data', (row) => {
            // Build javascript object
           return myMap[row['key']] = row['value'];
        })
        .on('end', () => {
            console.log('Done.');
        });
}
async function processHttpRequest(map)
{
    try
    {
        let reqres = await httpReuqest(map); // Your defined function for httpReuqest
    }
    catch (e)
    {

    }

}
processCSV();
processHttpReuqet();
1 голос
/ 28 марта 2019

Как насчет обеспечения прослушивания http-объекта после загрузки файла в память:


// server.js
var myMap = {};

function readCsv(cb){
  fs.createReadStream('filename.csv')  
  .pipe(csv())
  .on('data', (row) => {
    // Build javascript object
    myMap[row['key']] = row['value'];
  })
  .on('end', () => {
    console.log('Done.');
    cb();
  });
}

var app = express();

exports = Object.freeze({
  server: http.createServer(app)
  init(){
    readCsv(() => {
      this.server.listen(80)
    })
  }
})

Что-то в этом роде.

Вы также можете использовать Promise

// server.js
var myMap = {};

function readCsv(){
  return new Promise((request, reject) => {
    fs.createReadStream('filename.csv')  
    .pipe(csv())
    .on('data', (row) => {
      // Build javascript object
      myMap[row['key']] = row['value'];
    })
    .on('end', () => {
      console.log('Done.');
      resolve();
    })
    .on('error', reject)
  })

}

var app = express();

exports = Object.freeze({
  server: http.createServer(app)
  init(){
    return readCsv().then(() => {
      this.server.listen(80)
    })
  }
})

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

Для достижения обеих ваших целей вы можете включить код в файл app.js.App.js запускается только при запуске экспресс-сервера.Не обновляется при обновлении страницы.Вы можете запустить app.listen после окончания чтения.

var myMap = {};

fs.createReadStream('filename.csv')  
  .pipe(csv())
  .on('data', (row) => {
    // Build javascript object
    myMap[row['key']] = row['value'];
  })
  .on('end', () => {
    app.listen(port, () => console.log(`Example app listening on port ${port}!`));
  });

Однако, поскольку я не думаю, что у вас будет много данных, лучше использовать синхронные (блокирующие) методы,как для парсера csv, так и для чтения файлов.Это просто облегчает понимание.Я использую csv-parse ниже.

const express = require('express')
const fs = require('fs')
const parse = require('csv-parse/lib/sync')

const app = express()
const port = 3000

/* In this example assume myMap will be
/ `
/ "key_1","key_2"
/ "value 1","value 2"
/ `
*/
var myMap = fs.readFileSync('sample.csv', 'utf8');

/* parsing the csv will return:
/  [Object {key_1: "value 1", key_2: "value 2"}]
*/
const records = parse(myMap, {
  columns: true,
  skip_empty_lines: true
})

app.get('/', (req, res) => res.send('Hello World!' + records[0].key_1))
app.listen(port, () => console.log(`Example app listening on port ${port}!`))

проверить его на runkit

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