Adding several text parts to one file in sequence In my script, node.js reads text files and generates text itself. At the end, I have five "text parts", and want to add them to one file. For this step, it must be considered that the sequence is important, so unfortunately the great async technique of node is obstructive. How would you handle this?

The five text parts consists of:


Read File "head.txt" and than write/append its text (not much data) to the file
Text (not much data) generated by node itself -> write/append its text to the file
Text (large data) generated by node itself (loop)
Text (large data) generated by node itself (loop)
Read File "footer.txt" and than write/append its text (normal size) to the file




var fs = require('fs');

var filename = "content.txt";

// (1) Read 'head.txt'
fs.readFileSync('head.txt', 'utf8', function (err, head) {
    if (err) {
        return console.log('Could not read file.');
    }
    fs.appendFile(filename, head);
    //var writeStream = fs.createWriteStream(filename);
    //writeStream.write(head);
});

// (2)
var a = '...';
var b = '...';
var ab = a + b;
//var writeStream = fs.createWriteStream(filename);
//writeStream.write(ab);
//writeStream.end();
fs.appendFileSync(filename, ab);


// (3)
var writeStream = fs.createWriteStream(filename);
for (i = 0; i &lt; xzy.length; i++) {
    writeStream.write('...' + xyz[i] + '...');
}
//writeStream.end();


// (4)
var writeStream = fs.createWriteStream(filename);
for (i = 0; i &lt; xyz.length; i++) {
    writeStream.write('...' + xyz[i] + '...');
}
//writeStream.end();


// (5) Read 'footer.txt'
fs.readFileSync('footer.txt', 'utf8', function (err, footer) {
if (err) {
    return console.log('Could not read file.');
}
var writeStream = fs.createWriteStream(filename);
writeStream.write(footer);
//writeStream.end();
});

/*writeStream.on('finish', function () {
    console.log('finish');
});
writeStream.on('close', function () {
    console.log('close');
});*/
Here we go, I would create some "util" namespace to write some helper code:

./util/index.js

const bPromise = require('bluebird');

const fs = require('fs');

const readFile = bPromise.promisify(fs.readFile);

const appendFile = bPromise.promisify(fs.appendFile);

const createWS = filename =&gt; {
    var writer = fs.createWriteStream(filename, {defaultEncoding: 'utf8', flags : 'a'});
    return {
        write : bPromise.promisify(writer.write.bind(writer))
    }
}

module.exports = {
    readFile, 
    appendFile,
    createWS
}


Thanks to bluebird we can convert functions with callback functions into functions that returns a resolved or rejected Promise with the result value. So that is what it's done in "./util/index.js".

In your main file:

var { readFile, appendFile, createWS} = require('./util');

var filename = "content.txt";
var writer = createWS(filename);
var xyz = ['x', 'y', 'z'];

// (1) Read 'head.txt'
readFile('head.txt', 'utf8')
.then( head =&gt; appendFile(filename, head))
.then( ()=&gt;{
    // Head appended
    var a = '...';
    var b = '...';
    var ab = a + b;
    return appendFile(filename, ab);
})
.then( ()=&gt;{
    // ab appended
    //return xyz.reduce((a, b)=&gt; a.then( ()=&gt; writer.write('...' + b + '...') ), Promise.resolve(null) )
    // or just 
    return writer.write(xyz.map(el=&gt;'...' + el + '...').join(''));
})
.then( ()=&gt;{
    return writer.write(xyz.map(el=&gt;'...' + el + '...').join(''));
})
.then( ()=&gt;{
    return readFile('footer.txt', 'utf8')
        .then( footer =&gt; writer.write(footer))
})
.then( ()=&gt;{})
.catch(console.error.bind(console));


Now looks very nice and it's clear. There's no need (Like in your code) to execute synchronous functions.

Check the ES5 code. 

./util/index.js

var bPromise = require('bluebird');

var fs = require('fs');

var readFile = bPromise.promisify(fs.readFile);

var appendFile = bPromise.promisify(fs.appendFile);

var createWS = function createWS(filename) {
    var writer = fs.createWriteStream(filename, { defaultEncoding: 'utf8', flags: 'a' });
    return {
        write: bPromise.promisify(writer.write.bind(writer))
    };
};

module.exports = {
    readFile: readFile,
    appendFile: appendFile,
    createWS: createWS
};


index.js

var _require = require('./util');

var readFile = _require.readFile;
var appendFile = _require.appendFile;
var createWS = _require.createWS;


var filename = "content.txt";
var writer = createWS(filename);
var xyz = ['x', 'y', 'z'];

// (1) Read 'head.txt'
readFile('head.txt', 'utf8').then(function (head) {
    return appendFile(filename, head);
}).then(function () {
    // Head appended
    var a = '...';
    var b = '...';
    var ab = a + b;
    return appendFile(filename, ab);
}).then(function () {
    // ab appended
    //return xyz.reduce((a, b)=&gt; a.then( ()=&gt; writer.write('...' + b + '...') ), Promise.resolve(null) )
    // or just 
    return writer.write(xyz.map(function (el) {
        return '...' + el + '...';
    }).join(''));
}).then(function () {
    return writer.write(xyz.map(function (el) {
        return '...' + el + '...';
    }).join(''));
}).then(function () {
    return readFile('footer.txt', 'utf8').then(function (footer) {
        return writer.write(footer);
    });
}).then(function () {}).catch(console.error.bind(console));