chemitaxis chemitaxis - 4 months ago 12
Node.js Question

How to improve this code in Node.js and Express.js avoiding callback hell

I have a method in one of my controller. The purpose of the controller, is print an array of urls using webshot package.

This is the code in question:

router.post('/capture', function (req, res, next) {

//Check params remove

var json = JSON.parse(req.body.data);

var promise = new Promise(function (resolve, reject) {

var totalImages = Object.keys(json).length;
var arrayListUrlImages = new Array(totalImages);
var counter = 0;
var completeDir = dir + ''; //Directory URL

for (var value of json) {
var url = 'http://example.com/' + id + '/' + value.anotherValue;
var folder = completeDir + id + '/' + value.anotherValue + '.jpg';

//Options for capturing image
var options = {
renderDelay: 1000,
quality: 100,
phantomConfig:
{
'local-to-remote-url-access': 'true',
'ignore-ssl-errors': 'true'
}
};

var anotherValue = value.anotherValue;

(function (anotherValue) {

webshot(url, folder, options, function (err) {
// screenshot now saved

if (err === null) {

var urlImage = "http://example.com/images/" + id + "/" + anotherValue + ".jpg";
arrayListUrlImages.push(urlImage);
counter++;
console.log("Counter: " + counter);

if (counter === totalImages) {
resolve(arrayListUrlImages);
}
}
else {
reject(err);
}
});
})(anotherValue);


}




}).then(function (arrayImages) {

res.send(arrayImages);


}).catch(function (errorVale) {
res.send(null);


});
});


This code is working without problems... but I would like to do better. I don't know how many URLs need to check (this is important detail because I need to do a for each or similar).

I have read about async package... Is better option move this code to something like async.parallel? Can I use yield in my code?

Thanks!

Answer

You don't need to use async for such simple example. Use native promises:

router.post('/capture', function (req, res, next) {

    //Check params remove 

    const json = JSON.parse(req.body.data);

    Promise.all(Object.getOwnPropertyNames(json).map((key) => {
        var value = json[key];

        var url = 'http://example.com/' + id + '/' + value.anotherValue;
        var folder = completeDir + id + '/' + value.anotherValue + '.jpg';

        //Options for capturing image
        var options = {
            renderDelay: 1000,
            quality: 100,
            phantomConfig:
            {
                'local-to-remote-url-access': 'true',
                'ignore-ssl-errors': 'true'
            }       
        };

        return new Promise((resolve, reject) => {
            webshot(url, folder, options, function (err) {
                if (err) {
                    reject(err);
                    return;
                }

                var urlImage = "http://example.com/images/" + id + "/" + anotherValue + ".jpg";
                resolve(urlImage);
            }
        });
    }))
    .then((listOfUrls) => {
        res.json(listOfUrls); // List of URLs
    }, (error) => {
        console.error(error);
        res.json(null);
    });
});
Comments