Node.js的http模块可用非常方便地请求网络资源,但是它不支持超时,这个挺不方便的;因为有些网络资源可能突然不可用了,我们不能等到系统自动超时才去做一些处理。实现一个也挺容易的,如下:

复制代码
function requestWithTimeout(options,timeout,callback){
    var timeoutEventId,
        req=http.request(options,function(res){
            
            res.on('end',function(){
                clearTimeout(timeoutEventId);
                console.log('response end...');
            });
            
            res.on('close',function(){
                clearTimeout(timeoutEventId);
                console.log('response close...');
            });
            
            res.on('abort',function(){
                console.log('abort...');
            });
            
            callback(res);
        });
        
    req.on('timeout',function(e){
        if(req.res){
            req.res('abort');
        }
        req.abort();
    });
    
    
    timeoutEventId=setTimeout(function(){
        req.emit('timeout',{message:'have been timeout...'});
    },timeout);
    
    return req;
}
复制代码

我们可用这样来调用requestWithTimeout方法:

 

复制代码
var http=require('http');
var options = {
  host: 'dict.youdao.com',
  port: 80,
  method: 'GET'
};
var req=requestWithTimeout(options,4000,function(res){
    res.on('data',function(chunk){
        console.log('body:'+chunk);
    });
});

req.on('error',function(e){
    console.log('error got :' + e.message);
}).on('timeout',function(e){
    console.log('timeout got :'+ e.message);
});

req.end();
复制代码

代码比较简单,也能很好地处理超时,但是,重新定义一个方法显得不怎么好,能否让http.request方法直接支持timeout呢?也就是说,直接在options参数中支持timeout属性。我们可用重写http.request方法,如下:

 

复制代码
http.request=(function(_request){
    return function(options,callback){
        var timeout=options['timeout'],
            timeoutEventId;
        var req=_request(options,function(res){
            res.on('end',function(){
                clearTimeout(timeoutEventId);
                console.log('response end...');
            });
            
            res.on('close',function(){
                clearTimeout(timeoutEventId);
                console.log('response close...');
            });
            
            res.on('abort',function(){
                console.log('abort...');
            });
            
            callback(res);
        });
        
        //超时
        req.on('timeout',function(){
            req.res && req.res.abort();
            req.abort();
        });
        
        //如果存在超时
        timeout && (timeoutEventId=setTimeout(function(){
            req.emit('timeout',{message:'have been timeout...'});
        },timeout));
        return req;
    };
    
})(http.request)
复制代码

调用就更直观了,和普通的request调用没啥区别,只是传入的options中多了timeout属性。

复制代码
var http=require('http');
var options = {
  host: 'dict.youdao.com',
  port: 80,
  method: 'GET',
  timeout:3000
};

var req = http.request(options, function(res) {
  console.log('STATUS: ' + res.statusCode);
  console.log('HEADERS: ' + JSON.stringify(res.headers));
  res.on('data', function (chunk) {
    console.log('BODY: ' + chunk);
  });
});

req.on('error',function(e){
    console.log("error got :"+e.message);
}).on('timeout',function(e){

    console.log('timeout got :'+e.message);
});

req.end();
复制代码

 

这样,我们就让http请求支持超时了。

http://www.cnblogs.com/flyingzl/articles/2286738.html