Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Promises with fs and bluebird

I'm currently learning how to use promises in nodejs

so my first challenge was to list files in a directory and then get the content of each with both steps using asynchronous functions. I came up with the following solution but have a strong feeling that this is not the most elegant way to do this, especially the first part where I am "turning" the asynchronous methods into promises

// purpose is to get the contents of all files in a directory
// using the asynchronous methods fs.readdir() and fs.readFile()
// and chaining them via Promises using the bluebird promise library [1]
// [1] https://github.com/petkaantonov/bluebird 

var Promise = require("bluebird");
var fs = require("fs");
var directory = "templates"

// turn fs.readdir() into a Promise
var getFiles = function(name) {
    var promise = Promise.pending();

    fs.readdir(directory, function(err, list) {
        promise.fulfill(list)
    })

    return promise.promise;
}

// turn fs.readFile() into a Promise
var getContents = function(filename) {
    var promise = Promise.pending();

    fs.readFile(directory + "/" + filename, "utf8", function(err, content) {
        promise.fulfill(content)
    })

    return promise.promise
}

Now chain both promises:

getFiles()    // returns Promise for directory listing 
.then(function(list) {
    console.log("We got " + list)
    console.log("Now reading those files\n")

    // took me a while until i figured this out:
    var listOfPromises = list.map(getContents)
    return Promise.all(listOfPromises)

})
.then(function(content) {
    console.log("so this is what we got: ", content)
})

As I wrote above, it returns the desired result, but I'm pretty sure there is a more elegant way to this.

like image 510
Henrik Avatar asked Oct 17 '13 14:10

Henrik


People also ask

What is Bluebird promises?

Apr 13, 2020. Bluebird is a popular promises library for JavaScript. It is a drop-in replacement for native Promises in JavaScript.

Why do we use Bluebird promises?

Bluebird can create a synchronous API from asynchronous code by wrapping generators in promise. coroutine. This means calling code need not worry about the promise or generator that's running behind the scenes in a given function. It can call the function like it's a simple synchronous function.

What does Promise Promisify do?

promisify. Returns a function that will wrap the given nodeFunction . Instead of taking a callback, the returned function will return a promise whose fate is decided by the callback behavior of the given node function.

What is Promisifyall?

promisify() Method. Digital ElectronicsElectronElectronics & Electrical. The util. promisify() method basically takes a function as an input that follows the common Node. js callback style, i.e., with a (err, value) and returns a version of the same that returns a promise instead of a callback.


1 Answers

The code can be made shorter by using generic promisification and the .map method:

var Promise = require("bluebird");
var fs = Promise.promisifyAll(require("fs")); //This is most convenient way if it works for you
var directory = "templates";

var getFiles = function () {
    return fs.readdirAsync(directory);
};
var getContent = function (filename) {
    return fs.readFileAsync(directory + "/" + filename, "utf8");
};

getFiles().map(function (filename) {
    return getContent(filename);
}).then(function (content) {
    console.log("so this is what we got: ", content)
});

In fact you could trim this even further since the functions are not pulling their weight anymore:

var Promise = require("bluebird");
var fs = Promise.promisifyAll(require("fs")); //This is most convenient way if it works for you
var directory = "templates";

fs.readdirAsync(directory).map(function (filename) {
    return fs.readFileAsync(directory + "/" + filename, "utf8");
}).then(function (content) {
    console.log("so this is what we got: ", content)
});

.map should be your bread and butter method when working with collections - it is really powerful as it works for anything from a promise for an array of promises that maps to further promises to any mix of direct values in-between.

like image 142
Esailija Avatar answered Sep 21 '22 15:09

Esailija