Node.js callback error

My problem is loading images with unknown extension (it could be "png" or "jpg" or "bmp" or so on). And I have some problems with the chekHead function returning a 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, the return length of the function; always returns 'underfined', but console.log returns a valid number; Why?

+3


source to share


2 answers


You have to use a callback to make it work the way you want:

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, due to your if-else logic, I don't see at the moment an option to use promises (jquery) instead of callbacks and nested callbacks, which can lead to callbacks - hell, which is kind of a bad model, so I'm sorry for that:

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 will take care of this. This is a good article article about the generator functions. And the basic idea is to use an exit for async methods or functions like request.head:



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

      

And use to get the length:

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

      

This is just my concept, I haven't proven it, but the Generator function notations work this way :)

+2


source


NodeJS executes your code in an asynchronous manner using callbacks. Your return might happen earlier (in which case it probably always does), the callback is complete. The variable length

is in return

undefined because it hasn't received any values.

You can use promises to bind a function or structure your code in a different way.



For promises see for example: 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;
}

      

+4


source







All Articles