nodejs发送http请求时遇到404长时间未响应的解决方法


Posted in NodeJs onDecember 10, 2017

通常,我们在使用nodejs发送http请求时,一旦遇到404响应,nodejs内部会一直请求下去,直到超出它自己设定的响应时长(最让人恶心的地方就是这个时长还是没法修改的。)很多人在这里碰到了麻烦。

我是在做arcgis地图项目的时候,客户提出需要使用天地图提供的底图服务,当时我直接使用silverlight客户端的Arcgis API进行http请求(同样是内部请求,不开源的东西就是这么让人郁闷),同样碰到了一个进度条一直卡在那的问题。经过调试发现,是由于底图加载请求超时的缘故,和nodejs一样,silverlight一直在进行请求直到超出它自己设定的响应时限。

于是,我当时正好有业余接触nodejs,觉得这个东西性能应该是不错的,至少比tomcat+java之流要好一些。于是,我着手写了一个nodejs的代理服务,用来请求天地图的底图。我当时以为nodejs碰到404时能直接结束请求,但是呢,这个问题好像是行业规范似的,它竟然也和silverlight一样不断的请求……索性上网查了会资料,得出了以下这两段代码,解决了这个一直请求404的问题。

function proxyTDTMapData(img,level,row,col){ 
  var that = this,request = null,param = img.replace('_w',''); 
  var filename = tdtimgDir+'/'+img+'_'+level+'_'+row+'_'+col+'.png'; 
  path.exists(filename, function(exists) { 
    if (exists) { 
      readFileEntry(filename,that.res); 
    }else{ 
      var url = "http://t0.tianditu.com/"+img+"/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=" + param + "&tileMatrixSet=w&TileRow=" + row + "&TileCol=" + col + "&TileMatrix=" + level + "&style=default&format=tiles"; 
       
      httpGetWithTimeoutSupport(url,4000,function(response){ 
        //console.log("have a response!"); 
        if(200 == response.statusCode){ 
          var size = 0; 
          var chunks = []; 
          response.on('data', function(chunk){ 
            size += chunk.length; 
            chunks.push(chunk); 
          }); 
          response.on('end', function(){ 
            var data = Buffer.concat(chunks, size); 
            that.res.writeHead(200, { 
              'Content-Type' : 'image/png', 
              'Content-Length' : data.length, 
              'Accept-Ranges' : 'bytes', 
              'Server' : 'Microsoft-IIS/7.5', 
              'X-Powered-By' : 'ASP.NET' 
            }); 
            that.res.write(data, "binary"); 
            that.res.end(); 
            fs.writeFile(tdtimgDir+'/'+img+'_'+level+'_'+row+'_'+col+'.png', data); 
           }); 
        }else{ 
          readFileEntry(mapDir+"/null.png",that.res); 
        } 
      }).on("error",function(){ 
        readFileEntry(mapDir+"/null.png",that.res); 
      }); 
    } 
  }); 
   
   
 }
function httpGetWithTimeoutSupport(options, timeout, callback) { 
  var timeoutEvent; 
 
  var req = http.get(options, function(res) { 
    res.on("end", function() { 
      clearTimeout(timeoutEvent); 
      // console.log("end"); 
    }) 
    res.on("close", function(e) { 
      clearTimeout(timeoutEvent); 
      // console.log("close"); 
    }) 
 
    res.on("abort", function() { 
      // console.log("abort"); 
    }); 
 
    res.on("error",function(){ 
      try{ 
        res.destory(); 
        clearTimeout(timeoutEvent); 
        //console.log("res error catch"); 
      }catch(e){ 
       
      } 
    }); 
    callback(res); 
  }); 
 
  req.on("timeout", function() { 
    //console.log("request emit timeout received"); 
    try{ 
      if (req.res) { 
        req.res.emit("abort"); 
      } 
      clearTimeout(timeoutEvent); 
      req.abort(); 
    }catch(e){ 
      //console.log("req timeout failed!"); 
    } 
  }); 
  req.on("error",function(){ 
    try{ 
      //console.log("req error catch"); 
    }catch(e){ 
     
    } 
  }); 
  timeoutEvent = setTimeout(function() { 
    try{ 
      req.emit("timeout"); 
    }catch(e){ 
      //console.log("timeout failed!"); 
    } 
  }, timeout); 
 
  return req; 
}

其原理就是利用nodejs请求的几个事件与计时器,一旦超出设定的响应时长则立马终结请求。如此,进度条一直卡着的问题解决了。
细心的读者可能看到了

path.exists(filename, function(exists) { 
    if (exists) { 
      readFileEntry(filename,that.res); 
    }else{...});

这段代码,其实这里做了一下服务端的图片缓存,一旦加载过的底图图片,直接从本地读取,极大的加快了地图的访问速度(这个在效率上提升了至少10倍)。
至于Arcgis API for Silverlight 是如何实现天地图底图以及其它底图服务(比如非标准墨卡托的地方坐标系底图服务)加载的呢?请听我下回分解。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

NodeJs 相关文章推荐
nodejs npm package.json中文文档
Sep 04 NodeJs
nodejs实现HTTPS发起POST请求
Apr 23 NodeJs
使用NodeJs 开发微信公众号(三)微信事件交互实例
Mar 02 NodeJs
详解Nodejs基于mongoose模块的增删改查的操作
Dec 21 NodeJs
实例分析nodejs模块xml2js解析xml过程中遇到的坑
Mar 18 NodeJs
nodejs获取微信小程序带参数二维码实现代码
Apr 12 NodeJs
Nodejs中的JWT和Session的使用
Aug 21 NodeJs
nodejs检测因特网是否断开的解决方案
Apr 17 NodeJs
nodejs开发一个最简单的web服务器实例讲解
Jan 02 NodeJs
nodeJs的安装与npm全局环境变量的配置详解
Jan 06 NodeJs
Nodejs文件上传、监听上传进度的代码
Mar 27 NodeJs
Nodejs环境实现socket通信过程解析
Jul 03 NodeJs
NodeJs实现定时任务的示例代码
Dec 05 #NodeJs
windows系统下更新nodejs版本的方案
Nov 24 #NodeJs
nodejs项目windows下开机自启动的方法
Nov 22 #NodeJs
使用nodeJs来安装less及编译less文件为css文件的方法
Nov 20 #NodeJs
NodeJS实现视频转码的示例代码
Nov 18 #NodeJs
详解NODEJS基于FFMPEG视频推流测试
Nov 17 #NodeJs
nodejs async异步常用函数总结(推荐)
Nov 17 #NodeJs
You might like
ajax+php打造进度条 readyState各状态
2010/03/20 PHP
php学习之 循环结构实现代码
2011/06/09 PHP
实例讲解php实现多线程
2019/01/27 PHP
HTML-CSS群中单选引发的“事件”
2007/03/05 Javascript
页面只有一个text的时候,回车自动submit的解决方法
2010/08/12 Javascript
jQuery EasyUI API 中文文档 - MenuButton菜单按钮使用介绍
2011/10/06 Javascript
Javascript玩转继承(一)
2014/05/08 Javascript
Javascript window对象详解
2014/11/12 Javascript
基于jquery实现的自动补全功能
2015/03/12 Javascript
AngularJS的表单使用详解
2015/06/17 Javascript
jQuery基础知识点总结(DOM操作)
2016/06/01 Javascript
jquery mobile 实现自定义confirm确认框效果的简单实例
2016/06/17 Javascript
JavaScript评论点赞功能的实现方法
2017/03/13 Javascript
利用Javascript开发一个二维周视图日历
2017/12/14 Javascript
详解React之父子组件传递和其它一些要点
2018/06/25 Javascript
JS实现图片切换效果
2018/11/17 Javascript
在Koa.js中实现文件上传的接口功能
2019/10/08 Javascript
微信小程序实现锚点功能
2019/11/20 Javascript
[02:33]2014DOTA2 TI每日综述 LGD涉险晋级DK闯入胜者组
2014/07/14 DOTA
[01:02:10]DOTA2上海特级锦标赛B组小组赛#2 VG VS Fnatic第一局
2016/02/26 DOTA
Python使用爬虫爬取静态网页图片的方法详解
2018/06/05 Python
python 读写文件,按行修改文件的方法
2018/07/12 Python
Python理解递归的方法总结
2019/01/28 Python
Python 经典算法100及解析(小结)
2019/09/13 Python
Python如何输出整数
2020/06/07 Python
HTML5 直播疯狂点赞动画实现代码 附源码
2020/04/14 HTML / CSS
世界第一冲浪品牌:O’Neill
2016/08/30 全球购物
德国原装品牌香水、化妆品和手表网站:BRASTY.DE
2016/10/16 全球购物
党组织公开承诺书
2014/03/29 职场文书
质量管理标语
2014/06/12 职场文书
2014应届本科生自我评价
2014/09/13 职场文书
成绩单评语
2015/01/04 职场文书
努力学习保证书
2015/02/26 职场文书
导游词之山西-五老峰
2019/10/07 职场文书
.Net Core导入千万级数据至Mysql的步骤
2021/05/24 MySQL
Android开发实现极为简单的QQ登录页面
2022/04/24 Java/Android