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实用示例 缩址还原
Dec 28 NodeJs
nodejs中转换URL字符串与查询字符串详解
Nov 26 NodeJs
Nodejs初级阶段之express
Nov 23 NodeJs
基于nodejs+express(4.x+)实现文件上传功能
Nov 23 NodeJs
windows 下安装nodejs 环境变量设置
Feb 02 NodeJs
用nodeJS搭建本地文件服务器的几种方法小结
Mar 16 NodeJs
NodeJs的fs读写删除移动监听
Apr 28 NodeJs
nodejs 搭建简易服务器的图文教程(推荐)
Jul 18 NodeJs
nodejs 图片预览和上传的示例代码
Sep 30 NodeJs
nodejs连接mysql数据库及基本知识点详解
Mar 20 NodeJs
nodejs使用node-xlsx生成excel的方法示例
Aug 22 NodeJs
nodejs脚本centos开机启动实操方法
Mar 04 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位运算的简单权限设计
2013/06/30 PHP
PHP-Fcgi下PHP的执行时间设置方法
2013/08/02 PHP
关于B/S判断浏览器断开的问题讨论
2008/10/29 Javascript
javascript 写类方式之七
2009/07/05 Javascript
javascript 文本框水印/占位符(watermark/placeholder)实现方法
2012/01/15 Javascript
javascript模拟实现C# String.format函数功能代码
2013/11/25 Javascript
jQuery事件绑定和委托实例
2014/11/25 Javascript
使用JavaScript的AngularJS库编写hello world的方法
2015/06/23 Javascript
详解AngularJS实现表单验证
2015/12/10 Javascript
JavaScript中实现键值对应的字典与哈希表结构的示例
2016/06/12 Javascript
分享bootstrap学习笔记心得(组件及其属性)
2017/01/11 Javascript
Jil,高效的json序列化和反序列化库
2017/02/15 Javascript
bootstrap栅格系统示例代码分享
2017/05/22 Javascript
Agularjs妙用双向数据绑定实现手风琴效果
2017/05/26 Javascript
JavaScript中in和hasOwnProperty区别详解
2017/08/04 Javascript
前端开发不得不知的10个最佳ES6特性
2017/08/30 Javascript
小程序实现留言板
2018/11/02 Javascript
微信小程序之几种常见的弹框提示信息实现详解
2019/07/11 Javascript
js实现翻牌小游戏
2020/07/31 Javascript
AJAX XMLHttpRequest对象创建使用详解
2020/08/20 Javascript
Go语言基于Socket编写服务器端与客户端通信的实例
2016/02/19 Python
Python打包方法Pyinstaller的使用
2018/10/09 Python
解决pycharm回车之后不能换行或不能缩进的问题
2019/01/16 Python
Python编程实现tail-n查看日志文件的方法
2019/07/08 Python
Python scipy的二维图像卷积运算与图像模糊处理操作示例
2019/09/06 Python
在Keras中实现保存和加载权重及模型结构
2020/06/15 Python
浅谈keras通过model.fit_generator训练模型(节省内存)
2020/06/17 Python
Python 实现一个简单的web服务器
2021/01/03 Python
初二物理教学反思
2014/01/29 职场文书
竞选班干部演讲稿100字
2014/08/20 职场文书
机关单位工作失职检讨书
2014/11/20 职场文书
2015年政府采购工作总结
2015/05/21 职场文书
2015年团支部年度工作总结
2015/05/27 职场文书
2015年党务工作者个人工作总结
2015/10/22 职场文书
Python探索生命起源 matplotlib细胞自动机动画演示
2022/04/21 Python
Pytorch中expand()的使用(扩展某个维度)
2022/07/15 Python