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开发微信公众号后台服务实例
Sep 03 NodeJs
nodejs事件的监听与触发的理解分析
Feb 12 NodeJs
Nodejs学习笔记之测试驱动
Apr 16 NodeJs
nodeJs爬虫获取数据简单实现代码
Mar 29 NodeJs
详解nodejs express下使用redis管理session
Apr 24 NodeJs
nodejs 搭建简易服务器的图文教程(推荐)
Jul 18 NodeJs
使用Nodejs连接mongodb数据库的实现代码
Aug 21 NodeJs
Nodejs 和Session 原理及实战技巧小结
Aug 25 NodeJs
NodeJS实现不可逆加密与密码密文保存的方法
Mar 16 NodeJs
基于nodejs res.end和res.send的区别
May 14 NodeJs
nodejs高大上的部署方式(PM2)
Sep 11 NodeJs
NodeJS开发人员常见五个错误理解
Oct 14 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漏洞小结
2012/02/05 PHP
php读取txt文件组成SQL并插入数据库的代码(原创自Zjmainstay)
2012/07/31 PHP
解析php中获取url与物理路径的总结
2013/06/21 PHP
laravel 5.4 + vue + vux + element的环境搭配过程介绍
2018/04/26 PHP
thinkPHP框架通过Redis实现增删改查操作的方法详解
2019/05/13 PHP
不用AJAX和IFRAME,说说真正意义上的ASP+JS无刷新技术
2008/09/25 Javascript
半角全角相互转换的js函数
2009/10/16 Javascript
JavaScript实现的圆形浮动标签云效果实例
2015/08/06 Javascript
Boostrap模态窗口的学习小结
2016/03/28 Javascript
浅谈javascript中的加减时间
2016/07/12 Javascript
移动端点击图片放大特效PhotoSwipe.js插件实现
2016/08/25 Javascript
利用node.js实现自动生成前端项目组件的方法详解
2017/07/12 Javascript
javascript原生封装一个淡入淡出效果的函数测试实例代码
2018/03/19 Javascript
vue axios封装及API统一管理的方法
2019/04/18 Javascript
ES6小技巧之代替lodash
2019/06/07 Javascript
javascript异常处理实现原理详解
2020/02/17 Javascript
Vue使用自定义指令实现拖拽行为实例分析
2020/06/06 Javascript
node.js如何根据URL返回指定的图片详解
2020/10/21 Javascript
Python实现Const详解
2015/01/27 Python
粗略分析Python中的内存泄漏
2015/04/23 Python
python实现带声音的摩斯码翻译实现方法
2015/05/20 Python
Windows下Anaconda的安装和简单使用方法
2018/01/04 Python
Python回文字符串及回文数字判定功能示例
2018/03/20 Python
Python里字典的基本用法(包括嵌套字典)
2019/02/27 Python
Python双链表原理与实现方法详解
2020/02/22 Python
Python ORM框架Peewee用法详解
2020/04/29 Python
解决Python Matplotlib绘图数据点位置错乱问题
2020/05/16 Python
localStorage 设置过期时间的方法实现
2018/12/21 HTML / CSS
7 For All Mankind官网:美国加州洛杉矶的高级牛仔服装品牌
2018/12/20 全球购物
编写一个 C 函数,该函数在一个字符串中找到可能的最长的子字符串,且该字符串是由同一字符组成的
2015/07/23 面试题
好的自荐信包括什么内容
2013/11/07 职场文书
会议邀请书范文
2014/02/02 职场文书
优秀高中生事迹材料
2014/02/11 职场文书
工程类专业自荐信范文
2014/03/09 职场文书
城管个人总结
2015/02/28 职场文书
个人年底工作总结
2015/03/10 职场文书