在浏览器中使用JavaScript渲染文本流

时间:2019-10-05 23:06:55

标签: javascript browser stream

使用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}

1 个答案:

答案 0 :(得分:0)

尝试:

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;
    }
}