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 相关文章推荐
使用forever管理nodejs应用教程
Jun 03 NodeJs
轻松创建nodejs服务器(2):nodejs服务器的构成分析
Dec 18 NodeJs
Nodejs的express使用教程
Nov 23 NodeJs
Nodejs从有门道无门菜鸟起飞必看教程
Jul 20 NodeJs
NodeJS处理Express中异步错误
Mar 26 NodeJs
nodejs个人博客开发第三步 载入页面
Apr 12 NodeJs
win系统下nodejs环境安装配置
May 04 NodeJs
nodejs批量下载图片的实现方法
May 19 NodeJs
详解nodejs解压版安装和配置(带有搭建前端项目脚手架)
Dec 06 NodeJs
监控Nodejs的性能实例代码
Jul 02 NodeJs
nodejs nedb 封装库与使用方法示例
Feb 06 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 mysql索引问题
2008/06/07 PHP
PHP中读取照片exif信息的方法
2014/08/20 PHP
Symfony的安装和配置方法
2016/03/17 PHP
javascript[js]获取url参数的代码
2007/10/17 Javascript
读jQuery之四(优雅的迭代)
2011/06/20 Javascript
关于extjs4如何获取grid修改后的数据的问题
2013/08/07 Javascript
JavaScript对内存分配及管理机制详细解析
2013/11/11 Javascript
JS判断不能为空实例代码
2013/11/26 Javascript
javascript正则匹配汉字、数字、字母、下划线
2014/04/10 Javascript
bootstrap改变按钮加载状态
2014/12/01 Javascript
JS中处理时间之setUTCMinutes()方法的使用
2015/06/12 Javascript
JavaScript实现经典排序算法之插入排序
2016/12/28 Javascript
微信小程序动态显示项目倒计时效果
2017/06/13 Javascript
JavaScript中document.referrer的用法详解
2017/07/04 Javascript
JavaScript实现二维坐标点排序效果
2017/07/18 Javascript
bootstrap table实现x-editable的行单元格编辑及解决数据Empty和支持多样式问题
2017/08/10 Javascript
JavaScript编写棋盘覆盖代码详解
2017/08/28 Javascript
VUE2.0+ElementUI2.0表格el-table实现表头扩展el-tooltip
2018/11/30 Javascript
Linux 发邮件磁盘空间监控(python)
2016/04/23 Python
Python编程实现蚁群算法详解
2017/11/13 Python
微信跳一跳python辅助软件思路及图像识别源码解析
2018/01/04 Python
Python使用matplotlib绘制正弦和余弦曲线的方法示例
2018/01/06 Python
Python实现中一次读取多个值的方法
2018/04/22 Python
python实现计数排序与桶排序实例代码
2019/03/28 Python
pyqt5中QThread在使用时出现重复emit的实例
2019/06/21 Python
Python自动化测试笔试面试题精选
2020/03/12 Python
纯CSS改变webkit内核浏览器的滚动条样式
2014/04/17 HTML / CSS
澳大利亚女士时装在线:Rockmans
2018/09/26 全球购物
澳大利亚墨水站Ink Station:墨水和碳粉打印机墨盒
2019/03/24 全球购物
查环查孕证明
2014/01/10 职场文书
工程类专业自荐信范文
2014/03/09 职场文书
2014全国两会大学生学习心得体会
2014/03/10 职场文书
幼儿园教师考核评语
2014/12/31 职场文书
杭白菊导游词
2015/02/10 职场文书
律政俏佳人观后感
2015/06/09 职场文书
2016高考冲刺决心书
2015/09/23 职场文书