1

I'm writing an extension for vscode and it is the first time I use JS (node.js, don't know if there is a difference) and it all works great except for the fs.append() function.

It seems to mix up inputs, so if input is:

Foo
Bar

It sometimes outputs:

Bar
Foo

but it doesn't happen all the time and i can't quite figure out why.

Here is my code (at least the important parts)

const fs = require('fs');

var path = 'includes/hello/hello.cpp';
var file = '.vscode/tasks.json';
var lineReader = require('readline').createInterface({
input: fs.createReadStream(file)});
lineReader.on('line', function(line) {
    fs.appendFile(file, line + '\n', function(err) {
        if(err) {
            return console.error(err);
        }
    });
});
Gama11
  • 31,714
  • 9
  • 78
  • 100

1 Answers1

1

You're calling .appendFile without waiting for the previous call to finish, so the order is not guaranteed, you should use a WriteableStream for this and split2 to split new lines so it's easier to control the backpressure of the WriteableStream, since you can pause/resume the stream when needed.

const fs = require('fs');
const path = 'includes/hello/hello.cpp';
const file = '.vscode/tasks.json';
const split2 = require('split2')
const { once } = require('events');


const writer = fs.createWriteStream('somefile', { flag: 'a' });

const stream = fs.createReadStream(file)
    .pipe(split2())

stream.on('data', async function (line) {
    if(!writer.write(line + '\n')) {
      stream.pause();
      await once(writer, 'drain'); // handle backpressure
      stream.resume();
    }
})

Now .write will make sure the chunks are written in the correct order.

An alternative would be to create an extra TransformStream and use .pipe instead.

const { Transform } = require('stream')

/* ... */

const myTransform = new Transform({
  transform(chunk, encoding, callback) {
    const newLine = Buffer.from('\n');
    // Do any transformation here
    callback(null, Buffer.concat([chunk, newLine]));
  }
});

fs.createReadStream(file)
    .pipe(split2())
    .pipe(myTransform)
    .pipe(writer)
Marcos Casagrande
  • 37,983
  • 8
  • 84
  • 98