在node.js中使用http.request如何捕捉ECONNREFUSED错误?

26

我正在尝试在Node.js中使用HTTP客户端时捕获ECONNREFUSED错误。我正在进行这样的请求:

var http = require('http');
var options = { host: 'localhost', port: '3301', path: '/', method: 'GET' };

http.request(options).on('response', function (res) {
  // do some stuff
});

我无法弄清如何捕获这个错误:

Error: connect ECONNREFUSED
  at errnoException (net.js:614:11)
  at Object.afterConnect [as oncomplete] (net.js:605:18)

如果我这样写 request.on('error', function () {});,它不会捕获错误。如果我像这样写:

var req = request.on(etc)
req.on('error', function blah () {});

然后我收到了 TypeError: Object false has no method 'on' 的错误信息。

我真的必须要处理这个顶级未捕获的错误吗?目前无论我做什么,整个进程都会退出。

编辑:我找到了一些关于如何创建一个 connection 对象、在其上调用 request 并绑定到 connection 对象上的错误的博客文章,但这难道不会使整个 http.request() 快捷方式失去意义吗?


2
我弄清楚了。这是因为我在这样做:var req = http.request(options).on('response', function (res) { // do some stuff }).end();req.on('error', handleError);我在调用 end() 后再调用 req.on。呵呵! - Cera
将来的话,您能否在这里发布那篇博客文章的链接?我认为这会非常有帮助。 - CSilivestru
4个回答

26

它不起作用<pre>var req = http.request("http://www.google.com/index.html", function(res) { console.log("Got response: " + res.statusCode); // 在这里绑定 'data','end' 事件 }); req.on('error', function(error) { console.log(error) // 错误处理在这里 }); req.end();</pre> - Codefor
你尝试过使用有效的选项对象作为第一个参数而不是传递URL吗? - Ryan Olds
3
使用 Node 10,我可以确认这个解决方案能够处理 ECONNREFUSE 错误。 - Owen Allen
1
还要注意'req'和'res'不是同一个东西。我为两者都处理了错误事件,以确保我的应用程序不会崩溃。 - Aebsubis

7
每次调用http.request()都返回其本身。因此请尝试如下操作...
http.request(options.function(){}).on('error',function(){}).end();

简单的解决方案!谢谢! - Alexandre Justino

6

我已经有一个解决方案了,尝试了许多这个页面(以及其他许多页面)上的建议。

我的客户端需要检测一个运行嵌入式Windows的交钥匙产品。该客户端是从一个不同的机器上提供服务给交钥匙产品。

交钥匙产品可以处于3种状态中的一种:

  1. 关闭
  2. 启动Windows,但未运行交钥匙应用程序
  3. 运行交钥匙应用程序

我的客户端向我的nodejs/express服务发送“查找交钥匙产品”的GET消息,然后通过http.request尝试找到交钥匙产品。每个用例的行为如下:

  1. 超时
  2. ECONNREFUSED - 因为交钥匙产品的Windows嵌入式阶段拒绝连接。
  3. 请求的正常响应(顺利情况)

下面的代码处理了所有三种情况。捕获ECONNREFUSED事件的诀窍是了解到它的处理程序绑定到套接字事件。

var http = require('http');
var express = require('express');
var url = require('url');


function find (req, res) {
    var queryObj = url.parse(req.url, true).query;

    var options = {
        host: queryObj.ip, // client attaches ip address of turnkey to url.
        port: 1234,
        path: '/some/path',
    }; // http get options

    var badNews = function (e) {
        console.log (e.name + ' error: ', e.message);
        res.send({'ok': false, 'msg': e.message});
    }; // sends failure messages to log and client  

    // instantiate http request object and fire it
    var msg = http.request(options, function (response) {
        var body = '';

        response.on ('data', function(d) {
            body += d;
        }); // accumulate response chunks  

        response.on ('end', function () {
            res.send({'ok': true, 'msg': body});
            console.log('sent ok');
        }); // done receiving, send reply to client

        response.on('error', function (e) {
            badNews(e);
        }); // uh oh, send bad news to client   
    });

    msg.on('socket', function(socket) { 
        socket.setTimeout(2000, function () {   // set short timeout so discovery fails fast
            var e = new Error ('Timeout connecting to ' + queryObj.ip));
            e.name = 'Timeout';
            badNews(e);
            msg.abort();    // kill socket
        });
        socket.on('error', function (err) { // this catches ECONNREFUSED events
            badNews(err);
            msg.abort();    // kill socket
        });
    }); // handle connection events and errors

    msg.on('error', function (e) {  // happens when we abort
        console.log(e);
    });

    msg.end();
}

0

对于那些不使用 DNS 的人(你也可以使用 request 代替 get,只需将 get 替换为 request,像这样:http.request({ ... })):

http.get({ 
    host: '127.0.0.1',
    port: 443,
    path: '/books?author=spongebob',
    auth: 'user:p@ssword#'
 }, resp => {
    let data;

    resp.on('data', chunk => {
        data += chunk;
    });

    resp.on('end', () => console.log(data));
}).on('error', err => console.log(err));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接