Итак, я играл с NodeJS, и я пытаюсь получить файл, который отправляет клиент, обработать файл (без его сохранения, требует построчного процесса), а затем отправить результат процесса как загрузка файла.
Итак, у меня есть следующий маршрут:
app.post('/processFile', function(req, res) {
var file = req.files.file;
//Process file inline
process.processFile(file, req).then((data) => {
//res.setHeader('Content-Length', stat.size);
res.setHeader('Content-Type', 'text/plain');
res.setHeader('Content-Disposition', 'attachment; filename=tokenized.txt');
res.write(data, 'binary');
res.end();
}).catch((err) => {
res.send(err);
});
});
Функция processFile выглядит так:
processFile: function(file) {
return new Promise(function(resolve, reject) {
var lineReader = require('readline').createInterface({
input: fs.ReadStream(file)
});
var output = "";
lineReader.on('line', function(line) {
// Tokenize each line
DoSomethingFunction(line).then((data) => {
output += data + "\n";
}).catch((err) => {
reject(`Error in line [${line}].`);
});
});
resolve(output);
});
}
Когда я его тестирую, он ничего не делает. Я просто получаю пустой ответ, я провел несколько тестов и заметил, что маршрут получает reject () из обещания processFile (), но у него нет сообщения. После еще нескольких тестов я заметил, что:
var lineReader = require('readline').createInterface({
input: fs.ReadStream(file)
});
не работает, и это тот, кто отправляет "отклонить".
Есть идеи, что не так?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Проблема в том, что lineReader использует асинхронное событие для сбора информации.
По сути, это означает, что вы вызываете resolve(output) до того, как линейный ридер обработает какие-либо данные. Вместо этого вам нужно будет прослушать другое событие: событие "закрыть". Это означает, что линейный ридер готов.
lineReader.on('close', () => {
resolve(output);
});
Однако есть одно предостережение. Ваш DoSomethingFunction также кажется асинхронным. Это означает, что он может ждать, чтобы выполнить некоторую работу, когда запускается событие 'close'. Один из способов справиться с этим - сохранить самый последний результат DoSomethingFunction и присоединить к нему в событии «закрыть».
// Initialize to a resolved promise just in case you don't receive
// any data from the user
let doSomethingPromise = Promise.resolve();
lineReader.on('line', (line) => {
doSomethingPromise = DoSomethingFunction(line)
.then((data) => {
output += data + '\n';
})
.catch((err) => {
reject(`Error in line [${line}].`);
});
});
lineReader.on('close', () => {
// Wait for the DoSomethingFunction to finish
doSomethingPromise.then(() => resolve(output));
});
@FedeE. Это уже другая ошибка. Вероятно, это связано с тем, какова ценность file, и, возможно, с тем фактом, что вы используете fs.ReadStream вместо new fs.ReadStream или fs.createReadStream.
да ... Мне удалось это исправить ... но я не могу дождаться завершения всего процесса, чтобы "выпустить" команду resolve ()
@FedeE. Вы видели, что я сделал, сохранив обещание от DoSomethingFunction? Это должно заставить его работать правильно
Да, однако, мне пришлось создать массив в событии строки, а затем запустить построчную обработку после получения события закрытия, так как мне нужно было поддерживать порядок на выходе. Но ваш ответ помог понять, как это работает. Спасибо.
Спасибо, Майк. Теперь я получаю сообщение об ошибке в строке чтения: TypeError: путь должен быть строкой или буфером.