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实现Websocket的数据接收与发送
Nov 19 NodeJs
nodeJS删除文件方法示例
Dec 25 NodeJs
实例分析nodejs模块xml2js解析xml过程中遇到的坑
Mar 18 NodeJs
nodejs入门教程五:连接数据库的方法分析
Apr 24 NodeJs
NodeJS创建最简单的HTTP服务器
May 15 NodeJs
Nodejs搭建wss服务器教程
May 24 NodeJs
nodejs前端自动化构建环境的搭建
Jul 26 NodeJs
基于nodejs实现微信支付功能
Dec 20 NodeJs
nodejs初始化init的示例代码
Oct 10 NodeJs
nodejs实现范围请求的实现代码
Oct 12 NodeJs
用Electron写个带界面的nodejs爬虫的实现方法
Jan 29 NodeJs
nodejs log4js 使用详解
May 31 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 网页播放器用来播放在线视频的代码(自动判断并选择视频文件类型)
2010/06/03 PHP
Yii中表单用法实例详解
2016/01/05 PHP
php实现微信支付之企业付款
2018/05/30 PHP
[原创]静态页面也可以实现预览 列表不同的显示方式
2006/10/14 Javascript
基于jquery的一个简单的脚本验证插件
2010/04/05 Javascript
再论Javascript的类继承
2011/03/05 Javascript
JQuery 获取json数据$.getJSON方法的实例代码
2013/08/02 Javascript
JS+flash实现chrome和ie浏览器下同时可以复制粘贴
2013/09/22 Javascript
js实现按Ctrl+Enter发送效果
2014/09/18 Javascript
jQuery设置指定网页元素宽度和高度的方法
2015/03/25 Javascript
JS/jQ实现免费获取手机验证码倒计时效果
2016/06/13 Javascript
JavaScript自定义分页样式
2017/01/17 Javascript
JavaScript实现垂直滚动条效果
2017/01/18 Javascript
js Canvas绘制圆形时钟教程
2017/02/06 Javascript
JavaScript使用ZeroClipboard操作剪切板
2017/05/10 Javascript
vue单页开发父子组件传值思路详解
2018/05/18 Javascript
node中的密码安全(加密)
2018/09/17 Javascript
vue实现弹框遮罩点击其他区域弹框关闭及v-if与v-show的区别介绍
2018/09/29 Javascript
使用PYTHON创建XML文档
2012/03/01 Python
用Python操作字符串之rindex()方法的使用
2015/05/19 Python
解析Mac OS下部署Pyhton的Django框架项目的过程
2016/05/03 Python
python装饰器初探(推荐)
2016/07/21 Python
Python实现简单过滤文本段的方法
2017/05/24 Python
mac安装scrapy并创建项目的实例讲解
2018/06/13 Python
django admin 后台实现三级联动的示例代码
2018/06/22 Python
python ChainMap的使用和说明详解
2019/06/11 Python
Python的控制结构之For、While、If循环问题
2020/06/30 Python
python海龟绘图之画国旗实例代码
2020/11/11 Python
CSS3的transition和animation的用法实例介绍
2014/08/20 HTML / CSS
详解FireFox下Canvas使用图像合成绘制SVG的Bug
2019/07/10 HTML / CSS
中国京东和泰国中央集团合资的网站:JD CENTRAL
2020/08/22 全球购物
新春联欢会主持词
2014/03/24 职场文书
理财计划书
2014/08/14 职场文书
合作经营协议书范本
2014/09/16 职场文书
李白经典诗之一:全文无一“月”字,却句句有月
2019/07/12 职场文书
redis使用不当导致应用卡死bug的过程解析
2021/07/01 Redis