Usando un servidor nodejs, necesito transmitir los datos que se muestran a continuación desde un archivo de texto al navegador del cliente.
Cada línea del archivo de texto es un objeto json que representa un registro en la tabla.

{"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}
...

La función nodejs que se muestra al final de esta publicación transmite con éxito el archivo de texto a un nuevo archivo en el servidor.
Entonces el sourceStream es bueno.
La función también envía el sourceStream al navegador a través de devolución de llamada.

Cuando console.log(responseTextStream) en el navegador del cliente obtengo el siguiente búfer.
[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, ...]
Entonces sé que los datos están llegando al cliente.

Mi problema es: no sé cómo trabajar con la transmisión en el cliente.
El siguiente pseudocódigo muestra lo que estoy tratando de hacer con la transmisión usando javascript en el navegador.
¿Alguien puede ponerme en el camino correcto?
Gracias, john

// 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.

Esta es la función del servidor nodejs que transmite mi archivo de texto al navegador.
Esto funciona bien. No hay ningún problema aquí. Se incluye solo para mayor claridad.

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}
0
John Shearing 6 oct. 2019 a las 02:06

1 respuesta

La mejor respuesta

Tratar:

var Astr = responseTextStream;
var line = "";
for(var i=0; i<Astr.length; i++){
    var chr = String.fromCharCode(Astr[i]);
    if(chr == "\n" || chr == "\r"){
        console.log("line: ",line);
        // do something with the line here
        // clear the line buffer to start the next line.
        line = "";
    } else {
        line += chr;
    }
}
0
bob 5 oct. 2019 a las 23:58