3

My issue is downloading images with unknown extension( it may be 'png' or 'jpg' or 'bmp' or etc...).And I have some troubles with function chekHead's returning value:

var fs = require('fs'),
    request = require('request');
var processImg = function (uri,filename){
    if(checkHead(uri + 'png') > 2000){
        download(uri + 'png', filename + '.png', function(){
            console.log(uri + 'png' + " - downloaded")
        })
    }else if(checkHead(uri + 'jpg') > 2000){
        download(uri + 'jpg', filename + '.jpg', function(){
            console.log(uri + 'jpg' + " - downloaded")
        })
    }else if(checkHead(uri + 'bmp') > 2000) {
        download(uri + 'bmp', filename + '.bmp', function () {
            console.log(uri + 'bmp' + " - downloaded")
        })
    }

}


var checkHead = function(uri){
    var length;
    request.head(uri, function(err, res, body){
        if(err) return console.log("Error");

        length = res.headers['content-length'];
        console.log(length);
    });
    return length;
}


var download = function(uri, filename, callback){
    request(uri).pipe(fs.createWriteStream('./static/' + filename).on('close', callback));
};

So in checkHead function return length; always returns 'underfined', but console.log returns valid number; Why?

2 Answers 2

4

NodeJS executes your code in an asynchronous way using callbacks. Your return could happen before (in this case it's probably always the case) the callback is completed. The variable length is at the return undefined, because it hasn't received any values.

You could use promises to chain the function or you structure your code in another way.

For promises see e.g.: async q

var checkHead = function(uri){
    var length;

    // Callback is probably invoked after the return
    request.head(uri, function(err, res, body){
        if(err) return console.log("Error");

        length = res.headers['content-length'];
        console.log(length);
    });

   // gets executed directly
    return length;
}
Sign up to request clarification or add additional context in comments.

Comments

2

You have to use a callback so that is works the way you want it:

var checkHead = function(uri,callback){
    request.head(uri, function(err, res, body){
        if(err) return console.log("Error");

        var length = res.headers['content-length'];
        console.log(length);
        callback(length);
    });
};

Unfortunately because of your if-else logic I see no way at the moment to use promises(jquery) instead of callbacks and nested callbacks that can lead to callback-hell that is kind of bad pattern so I say sorry for this:

checkHead(uri + 'png',function(length){
   if(length > 2000){
      download(uri + 'png', filename + '.png', function(){
        console.log(uri + 'png' + " - downloaded")
      });
   }
   else{  
      checkHead(uri + 'jpg',function(length){
         if(length > 2000){
            download(uri + 'jpg', filename + '.jpg', function(){
               console.log(uri + 'jpg' + " - downloaded")
            });
         }
         else{
            checkHead(uri + 'bmp',function(length){
                if(length > 2000){
                    download(uri + 'jpg', filename + '.jpg', function(){
                         console.log(uri + 'jpg' + " - downloaded")
                    });
                }
            });
         }
      });
   }

});

BUT EcamScript 6 takes care of that. This is a good article about Generator Functions. And the main idea is to use yield for asynchronous methods or functions like request.head:

var checkHead = function*(uri){
    var length = yield request.head(uri);
};

And use next to get length:

checkHead.next();//{value: 123, done: true}

This is only my concept i did not prove this but Generator Functions notations work in this way :)

3 Comments

Thx,got it . But how I can use my if/else statements, for image extenstion manipulatiion
wow, very appreciate). I think I can rule that with async.waterfall
Yes, absolutely it actually must be avoided but ES6(EcmaScript 6) takes care of that soon. You are welcome :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.