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服务器(2):nodejs服务器的构成分析
Dec 18 NodeJs
轻松创建nodejs服务器(9):实现非阻塞操作
Dec 18 NodeJs
NodeJS制作爬虫全过程
Dec 22 NodeJs
NodeJS学习笔记之(Url,QueryString,Path)模块
Jan 13 NodeJs
iPhone手机上搭建nodejs服务器步骤方法
Jul 06 NodeJs
nodejs+express实现文件上传下载管理网站
Mar 15 NodeJs
详解nodejs模板引擎制作
Jun 14 NodeJs
nodejs中解决异步嵌套循环和循环嵌套异步的问题
Jul 12 NodeJs
Nodejs实现的操作MongoDB数据库功能完整示例
Feb 02 NodeJs
NodeJs入门教程之定时器和队列
Mar 08 NodeJs
使用nodejs分离html文件里的js和css详解
Apr 12 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
php feof用来识别文件末尾字符的方法
2010/08/01 PHP
Array of country list in PHP with Zend Framework
2011/10/17 PHP
thinkPHP实现递归循环栏目并按照树形结构无限极输出的方法
2016/05/19 PHP
PHP实现防盗链的方法分析
2017/07/25 PHP
PHP简单实现解析xml为数组的方法
2018/05/02 PHP
PHP+Oracle本地开发环境搭建方法详解
2019/04/01 PHP
解决 FireFox 下[使用event很麻烦] 的问题.
2006/08/22 Javascript
JS中实现replaceAll的方法(实例代码)
2013/11/12 Javascript
JQuery实现动态添加删除评论的方法
2015/05/18 Javascript
常见JS验证脚本汇总
2015/12/01 Javascript
javascript模块化简单解析
2016/04/07 Javascript
关于微信上网页图片点击全屏放大效果
2016/12/19 Javascript
Angular 2父子组件数据传递之@Input和@Output详解 (上)
2017/07/05 Javascript
Bootstrap一款超好用的前端框架
2017/09/25 Javascript
JS实现HTML页面中动态显示当前时间完整示例
2018/07/30 Javascript
RxJS的入门指引和初步应用
2019/06/15 Javascript
vue-cli创建的项目中的gitHooks原理解析
2020/02/14 Javascript
[06:30]DOTA2英雄梦之声_第15期_死亡先知
2014/06/21 DOTA
用Python输出一个杨辉三角的例子
2014/06/13 Python
python中迭代器(iterator)用法实例分析
2015/04/29 Python
python把1变成01的步骤总结
2019/02/27 Python
浅谈python之高阶函数和匿名函数
2019/03/21 Python
Python如何使用函数做字典的值
2019/11/30 Python
ASP.NET Core中的配置详解
2021/02/05 Python
美国女士时尚珠宝及配饰购物网站:Icing
2018/07/02 全球购物
全球立体声:World Wide Stereo
2018/09/29 全球购物
英国IT硬件供应商,定制游戏PC:Mesh Computers
2019/03/28 全球购物
《花木兰》教学反思
2014/04/09 职场文书
优秀团员事迹材料2000字
2014/08/20 职场文书
质监局领导班子践行群众路线整改方案
2014/10/26 职场文书
协议书范文
2015/01/27 职场文书
2015年宣传工作总结
2015/04/08 职场文书
pytorch 如何使用batch训练lstm网络
2021/05/28 Python
进阶篇之linux环境下安装MySQL数据库
2022/04/09 MySQL
Python使用mitmproxy工具监控手机 下载手机小视频
2022/04/18 Python
python中使用redis用法详解
2022/12/24 Redis