node.js回调值有问题

时间:2015-06-27 19:17:47

标签: javascript node.js

我的问题是下载未知扩展程序的图片(可能是' png'或者' jpg'或者' bmp'或等等...)。功能chekHead的返回值有一些麻烦:

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));
};

因此,在 checkHead 函数返回长度; 始终返回' underfined',但console.log返回有效数字;为什么呢?

2 个答案:

答案 0 :(得分:4)

NodeJS使用回调以异步方式执行代码。您的返回可能发生在之前(在这种情况下可能总是如此)回调完成。变量length位于return未定义,因为它未收到任何值。

您可以使用promises来链接函数,或者以另一种方式构建代码。

对于承诺,例如: 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;
}

答案 1 :(得分:2)

您必须使用回调,以便按您希望的方式运行:

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);
    });
};

不幸的是,由于你的if-else逻辑,我认为目前没有办法使用promises(jquery)而不是回调和嵌套回调可能导致回调 - 地狱这是一种糟糕的模式,所以我对此抱歉:

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负责这一点。关于生成器函数,这是一个很好的article。主要思想是为异步方法或函数使用yield,例如 request.head

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

然后使用next to get length:

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

这只是我的概念,我没有证明这一点,但生成器函数符号以这种方式工作:)