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 相关文章推荐
使用Angular和Nodejs、socket.io搭建聊天室及多人聊天室
Aug 21 NodeJs
nodejs连接mongodb数据库实现增删改查
Dec 01 NodeJs
nodejs实现发出蜂鸣声音(系统报警声)的方法
Jan 18 NodeJs
NodeJS仿WebApi路由示例
Feb 28 NodeJs
nodejs中向HTTP响应传送进程的输出
Mar 19 NodeJs
nodejs前端自动化构建环境的搭建
Jul 26 NodeJs
nodejs实现解析xml字符串为对象的方法示例
Mar 14 NodeJs
Nodejs异步回调之异常处理实例分析
Jun 22 NodeJs
详解nodejs 配置文件处理方案
Jan 02 NodeJs
nodejs中实现修改用户路由功能
May 24 NodeJs
通过Nodejs搭建网站简单实现注册登录流程
Jun 14 NodeJs
如何利用nodejs实现命令行游戏
Nov 24 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写的带缓存数据功能的mysqli类
2012/09/06 PHP
30个php操作redis常用方法代码例子
2014/07/05 PHP
详谈PHP面向对象中常用的关键字和魔术方法
2017/02/04 PHP
PHP递归实现文件夹的复制、删除、查看大小操作示例
2017/08/11 PHP
同域jQuery(跨)iframe操作DOM(实例讲解)
2013/12/19 Javascript
js中opener与parent的区别详细解析
2014/01/14 Javascript
Jquery1.9.1源码分析系列(十五)动画处理之外篇
2015/12/04 Javascript
jQuery实时显示鼠标指针位置和键盘ASCII码
2016/03/28 Javascript
JS中IP地址与整数相互转换的实现代码
2017/04/10 Javascript
AngularJS 教程及实例代码
2017/10/23 Javascript
webpack多入口文件页面打包配置详解
2018/01/09 Javascript
微信小程序用户信息encryptedData详解
2018/08/24 Javascript
微信小程序解析富文本过程详解
2019/07/13 Javascript
详解基于Vue/React项目的移动端适配方案
2019/08/23 Javascript
JavaScript实现简单计算器功能
2019/12/19 Javascript
在实例中重学JavaScript事件循环
2020/12/03 Javascript
[01:10:30]DOTA2-DPC中国联赛正赛 Dragon vs Dynasty BO3 第一场 3月4日
2021/03/11 DOTA
python实现用户管理系统
2018/01/10 Python
Python利用splinter实现浏览器自动化操作方法
2018/05/11 Python
python实现合并多个list及合并多个django QuerySet的方法示例
2019/06/11 Python
Django实现微信小程序的登录验证功能并维护登录态
2019/07/04 Python
超实用的 30 段 Python 案例
2019/10/10 Python
Python实现图像去噪方式(中值去噪和均值去噪)
2019/12/18 Python
Python-numpy实现灰度图像的分块和合并方式
2020/01/09 Python
优瑞自动咖啡机官网:Jura
2018/09/29 全球购物
意大利奢侈品购物网站:Deliberti
2019/10/08 全球购物
Nasty Gal英国:美国女性服饰销售网站
2021/03/02 全球购物
俄罗斯外国汽车和国产汽车配件网上商店:Движком
2020/04/19 全球购物
MAC彩妆澳洲官网:M·A·C AU
2021/01/17 全球购物
婚假请假条格式及范文
2014/04/10 职场文书
班组长安全工作职责
2014/07/15 职场文书
农村党支部书记党群众路线四风问题整改措施
2014/09/26 职场文书
学习党章的体会
2014/11/07 职场文书
2014年招商引资工作总结
2014/11/22 职场文书
2015年护理工作总结范文
2015/04/03 职场文书
ssh服务器拒绝了密码 请再试一次已解决(亲测有效)
2022/08/14 Servers