Используя сервер nodejs, мне нужно передать данные, показанные ниже, из текстового файла в браузер клиента.
Каждая строка в текстовом файле представляет собой объект json, представляющий запись в таблице.
{"userId":443,"email":"bob@gmail.com","hashedPassword":"36583a77a098c02ef111e2f2521d77b58e420f2bc7e9bf930ec24b21d42ea2e0","timeStamp":1567439821109,"deleted":false}
{"userId":447,"email":"alice@gmail.com","hashedPassword":"36583a77a098c02ef111e2f2521d77b58e420f2bc7e9bf930ec24b21d42ea2e0","timeStamp":1567439909013,"deleted":false}
{"userId":451,"email":"cliff@gmail.com","hashedPassword":"36583a77a098c02ef111e2f2521d77b58e420f2bc7e9bf930ec24b21d42ea2e0","timeStamp":1567443638340,"deleted":false}
...
Функция nodejs, показанная в конце этого поста, успешно передает текстовый файл в новый файл на сервере.
Таким образом, sourceStream хорош.
Функция также отправляет sourceStream в браузер с помощью обратного вызова.
Когда я console.log(responseTextStream)
в браузере клиента, я получаю следующий буфер:
[123, 34, 117, 115, 101, 114, 73, 100, 34, 58, 52, 52, 51, 44, 34, 101, 109, 97, 105, 108, 34, 58, 34, 98, 111, 98, 64, 103, 109, 97, 105, 108, 46, 99, 111, 109, 34, 44, 34, 116, 105, ...]
Итак, я знаю, что данные поступают на клиент.
Моя проблема: я не знаю, как работать с потоком на клиенте.
Следующий псевдокод показывает, что я пытаюсь сделать с потоком, используя javascript в браузере.
Может кто-нибудь, пожалуйста, поставьте меняна правильном пути?
Спасибо, Джон
// Populate the dbUsersList webpage with user records.
app.loadUsersListPage = function()
{
// Define which users will be retrieved from dbUsers.json
// This is not being used for now so all records will be retrived.
var QueryStringObject = {};
// Ask the server for the JSON records found in the dbUsers file which match the QueryStringObject.
// Then run the callback function defined here which inserts rows into the usersListTable on the webpage
// and populates them with data from the file of JSON records returned.
app.client.request(undefined,'api/aUsers','GET',QueryStringObject,undefined,function(statusCode,responseTextStream)
{
// if the call to handlers._users.get which is mapped to api/aUsers called back success.
if(statusCode == 200)
{
console.log(responseTextStream); // I can see the buffer is populated with data.
// Create a handle which can be used to manipulate the table on the webpage.
var table = document.getElementById("usersListTable");
// This next line causes an error because I am trying to use the
// split function on a stream but it demonstrates what I am
// trying to accomplish.
// I want to split the stream on each new line so that I can work
// with the json objects representing the records one at a time.
var recordsArray = responseTextStream.split('\n');
recordsArray.forEach(function(jsonString)
{
var recordObject = JSON.parse(jsonString);
if(recordObject)
{
// Insert a new row in the table.
var tr = table.insertRow(-1);
// Make the new row a member of the class 'checkRow'
tr.classList.add('checkRow');
// Insert five new cells into the new row.
var td0 = tr.insertCell(0);
var td1 = tr.insertCell(1);
var td2 = tr.insertCell(2);
var td3 = tr.insertCell(3);
// load the new cells with data from the recordObject.
td0.innerHTML = recordObject.userId;
td1.innerHTML = recordObject.email;
td2.innerHTML = recordObject.timeStamp;
td3.innerHTML = '<a href="/users/edit?email=' + recordObject.userId + '">View / Edit / Delete</a>';
}; // End of: if(recordObject)
}); // End of: recordsArray.forEach(...)
} // End of: if the call to handlers._users.get which is mapped to api/aUsers called back successfully.
} // End of: app.loadUsersListPage = function(){...}
// End of: Populate the dbUsersList webpage with user records.
Это серверная функция nodejs, которая передает мой текстовый файл в браузер.
Это прекрасно работает. Здесь нет проблем. Это включено только для ясности.
handlers._users.get = function(data, callback)
{
// Create an empty map data structure which will be used to merge user records with the same email address.
let usersMap = new Map();
// This function sets up a stream where each chunk of data is a complete line in the dbUsers file.
let readInterface = readline.createInterface
(
{ // specify the file to be read.
input: fs.createReadStream(_data.baseDir + '/dbPermissions/dbUsers' + '/' + 'dbUsers' + '.json'),
}
);
// Now look at each record in the file and merge them into a map.
readInterface.on('line', function(line)
{
// Convert the JSON string (a single line from the dbUsers file) into lineValueObject.
// These objects will written back to a new file after deleting some un-needed key/value pairs.
let lineValueObject = JSON.parse(line);
// Declare a variable to serve as a key in the map to manage the lineValueObject.
let userId = lineValueObject.userId;
if(lineValueObject.deleted === true)
{
// Remove this record from the map
usersMap.delete(userId);
}
else // this record has not been marked for deletion.
{
// Remove the hashed password key/value pair from the lineValueObject before returning it to the requester.
delete lineValueObject.hashedPassword;
// Remove the deleted key/value pair from the lineValueObject before returning it to the requester.
delete lineValueObject.deleted;
// Update this record in the map.
usersMap.set(userId, lineValueObject);
}
}); // End of: readInterface.on('line', function(line){...}
// End of: Look at each record...
// This listener fires after we have looked through all the records in the dbUsers file.
// The callback function defined here will stream the list of users back to the clients browser.
readInterface.on('close', function()
{
// This readable stream will be used to write the result of the merge to a new file.
const sourceStream = new Readable();
for (const [key, valueObject] of usersMap)
{
// Convert the data object to a string.
let stringData = JSON.stringify(valueObject);
// Load the readable stream with data.
sourceStream.push(stringData + '\n');
}
// Tell the stream no more data is coming.
sourceStream.push(null);
// Create a writable stream and specify the file which will receive the data from the readable stream.
let destinationStream = fs.createWriteStream(_data.baseDir + '/dbPermissions/dbUsers' + '/' + 'test' + '.txt', {flags : 'a'});
// Populate the new text file from the sourceStream.
// This is just to check that sourceStream is working as expected before sending the data to the client.
// The pipeline will be removed when my problem has been solved.
pipeline
(
sourceStream,
destinationStream,
function(error){if(error){console.log('There was an error.');}}
);
// Send the source stream to the client's browser
callback(200, sourceStream);
}); // End of: readInterface.on('close', function(){...}
}; // End of: handlers._users.get = function(data, callback){do stuff}