kirill.buga
kirill.buga

Reputation: 1159

Multiple writeFile in NodeJS

I have a task to write parts of the data to separate files:

        fs.writeFile('content/a.json', JSON.stringify(content.a, null, 4), function(err) {
            if(err) {
                console.log(err);
            } else {
                console.log('a.json was updated.');
            }
        });
        fs.writeFile('content/b.json', JSON.stringify(content.b, null, 4), function(err) {
            if(err) {
                console.log(err);
            } else {
                console.log('b.json was updated.');
            }
        });
        fs.writeFile('content/c.json', JSON.stringify(content.c, null, 4), function(err) {
            if(err) {
                console.log(err);
            } else {
                console.log('c.json was updated.');
            }
        });
        fs.writeFile('content/d.json', JSON.stringify(content.d, null, 4), function(err) {
            if(err) {
                console.log(err);
            } else {
                console.log('d.json was updated.');
            }
        });

But now I have 4 different callbacks, so I can't get the moment, when all 4 task have been finished. Is it possible to parallel 4 writeFile calls and get only 1 callback, which will be called when 4 files was created?

P.S.

Of course I can do smth like:

fs.writeFile('a.json', data, function(err) {
  fs.writeFile('b.json', data, function(err) {
    ....
    callback();
  }
}

Just curious is there any other way to do this. Thanks.

Upvotes: 6

Views: 13055

Answers (5)

Hai Alaluf
Hai Alaluf

Reputation: 937

With es6 you can do:

function writeFile(file, index) {
    return new Promise((resolve, reject) => {
        let  fileUrl = `content/${index}.json`;
        fs.writeFile(fileUrl, JSON.stringify(file, null, 4),
          (err) => {
              if (err)
                  reject (err);
              else
                  resolve(fileUrl)
          });
    });
}
let files = Object.keys(content).map(key => writeFile(content[key]));
Promise.all(files).then(values => {/*Files Urls*/}, err => {/*Some Error*/});

Upvotes: 0

Gergo Erdosi
Gergo Erdosi

Reputation: 42028

You can use the async module. It also helps cleaning up your code:

var async = require('async');

async.each(['a', 'b', 'c', 'd'], function (file, callback) {

    fs.writeFile('content/' + file + '.json', JSON.stringify(content[file], null, 4), function (err) {
        if (err) {
            console.log(err);
        }
        else {
            console.log(file + '.json was updated.');
        }

        callback();
    });

}, function (err) {

    if (err) {
        // One of the iterations produced an error.
        // All processing will now stop.
        console.log('A file failed to process');
    }
    else {
        console.log('All files have been processed successfully');
    }
});

Upvotes: 11

jfriend00
jfriend00

Reputation: 707158

I thought I'd offer a different approach using promises which are ideal for knowing when multiple async operations have all completed. This particular solution uses the Bluebird promise library:

var Promise = require('bluebird');
var fs = Promise.promisifyAll(require('fs'));

var promises = ["a", "b", "c", "d"].map(function(val) {
    return fs.writeFileAsync('content/' + val + ".json", JSON.stringify(content[val], null, 4));
});

Promise.all(promises).then(function() {
    // all writes are done here
}).catch(function(err) {
    // error here 
});

Upvotes: 1

fino
fino

Reputation: 3804

A cleaner way to do this .. would be to do it by async.map

var async = require('async');

var arr = [{'filename':'content/a.json', 'content':content.a},{'filename':'content/b.json', 'content':content.b}];
async.map(arr, getInfo, function (e, r) {
  console.log(r);
});

function getInfo(obj, callback) {
  fs.writeFile(obj.filename, JSON.stringify(obj.content, null, 4), callback);
}

Upvotes: 2

Michael
Michael

Reputation: 1322

Yes, you should use async, the parallel method looks like this:

async.parallel([
    function(callback){
        fs.writeFile('content/a.json', JSON.stringify(content.a, null, 4), callback);
    },
    function(callback){
        fs.writeFile('content/b.json', JSON.stringify(content.b, null, 4), callback);
    },
    function(callback){
        fs.writeFile('content/c.json', JSON.stringify(content.c, null, 4), callback);
    },
    function(callback){
        fs.writeFile('content/d.json', JSON.stringify(content.d, null, 4), callback);
    }
],
function(err, results){
    // all done
});

Upvotes: 4

Related Questions