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读取memcache示例分享
Jan 02 NodeJs
nodejs实现黑名单中间件设计
Jun 17 NodeJs
nodejs教程之制作一个简单的文章发布系统
Nov 21 NodeJs
NodeJS Web应用监听sock文件实例
Feb 18 NodeJs
Nodejs抓取html页面内容(推荐)
Aug 11 NodeJs
详解使用nodeJs安装Vue-cli
May 17 NodeJs
NodeJS自定义模块写法(详解)
Jun 27 NodeJs
nodejs使用express获取get和post传值及session验证的方法
Nov 09 NodeJs
M2实现Nodejs项目自动部署的方法步骤
May 05 NodeJs
nodejs对mongodb数据库的增加修删该查实例代码
Jan 05 NodeJs
nodejs脚本centos开机启动实操方法
Mar 04 NodeJs
windows如何把已安装的nodejs高版本降级为低版本(图文教程)
Dec 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
推荐几款用 Sublime Text 开发 Laravel 所用到的插件
2014/10/30 PHP
Yii 2.0实现联表查询加搜索分页的方法示例
2017/08/02 PHP
gearman中worker常驻后台,导致MySQL server has gone away的解决方法
2020/02/27 PHP
一文看懂PHP进程管理器php-fpm
2020/06/01 PHP
打开超链需要“确认”对话框的方法
2007/03/08 Javascript
复制小说文本时出现的随机乱码的去除方法
2010/09/07 Javascript
JavaScript中OnLoad几种使用方法
2012/12/15 Javascript
document.compatMode的CSS1compat使用介绍
2014/04/03 Javascript
js解决select下拉选不中问题
2014/10/14 Javascript
jQuery实现的图文高亮滚动切换特效实例
2015/08/10 Javascript
jquery实现红色竖向多级向右展开的导航菜单效果
2015/08/31 Javascript
JavaScript表单焦点自动切换代码
2016/07/24 Javascript
微信小程序购物商城系统开发系列-工具篇的介绍
2016/11/21 Javascript
JavaScript对象封装的简单实现方法(3种方法)
2017/01/03 Javascript
bootstrap警告框使用方法解析
2017/01/13 Javascript
Angular2 父子组件数据通信实例
2017/06/22 Javascript
微信小程序tabBar底部导航中文注解api详解
2017/08/16 Javascript
详解react-router 4.0 下服务器如何配合BrowserRouter
2017/12/29 Javascript
nodejs(officegen)+vue(axios)在客户端导出word文档的方法
2018/07/31 NodeJs
Python读取mat文件,并转为csv文件的实例
2018/07/04 Python
python的xpath获取div标签内html内容,实现innerhtml功能的方法
2019/01/02 Python
python卸载后再次安装遇到的问题解决
2019/07/10 Python
如何给Python代码进行加密
2020/01/10 Python
Python自定义sorted排序实现方法详解
2020/09/18 Python
python制作抽奖程序代码详解
2021/01/15 Python
Surfdome西班牙:世界上最受欢迎的生活方式品牌
2019/02/13 全球购物
生产部统计员岗位职责
2014/01/05 职场文书
文秘专业应届生求职信
2014/05/26 职场文书
小学竞选班干部演讲稿
2014/08/20 职场文书
社会发展项目建议书
2014/08/25 职场文书
单位工作证明范文
2014/09/14 职场文书
学校四风问题对照检查材料思想汇报
2014/09/26 职场文书
行风评议整改报告
2014/11/06 职场文书
2015年小学中秋节活动总结
2015/03/23 职场文书
毕业感言怎么写
2015/07/31 职场文书
Python帮你解决手机qq微信内存占用太多问题
2022/02/15 Python