本文介绍了nodejs - 如何承诺 http.request?拒绝被叫了两次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将 http.request 包装到 Promise 中:

I'm trying to wrap http.request into Promise:

 new Promise(function(resolve, reject) {
    var req = http.request({
        host: '127.0.0.1',
        port: 4000,
        method: 'GET',
        path: '/api/v1/service'
    }, function(res) {
        if (res.statusCode < 200 || res.statusCode >= 300) {
            // First reject
            reject(new Error('statusCode=' + res.statusCode));
            return;
        }
        var body = [];
        res.on('data', function(chunk) {
            body.push(chunk);
        });
        res.on('end', function() {
            try {
                body = JSON.parse(Buffer.concat(body).toString());
            } catch(e) {
                reject(e);
                return;
            }
            resolve(body);
        });
    });
    req.on('error', function(err) {
        // Second reject
        reject(err);
    });
    req.write('test');
}).then(function(data) {
    console.log(data);
}).catch(function(err) {
    console.log(err);
});

如果我从远程服务器收到错误的statusCode,它将调用第一次拒绝,一段时间后第二次拒绝.如何正确制作以便它只调用一次拒绝(我认为在这种情况下第一次拒绝是正确的)?我想我需要自己关闭 res,但是 ClientResponse 对象上没有 close() 方法.

If I recieve errornous statusCode from remote server it will call First reject and after a bit of time Second reject. How to make properly so it calls only single reject (I think First reject is proper one in this case)? I think I need to close res myself, but there is no close() method on ClientResponse object.

UPD:第二次拒绝很少触发 - 为什么?

UPD:Second reject triggers very rarely - why?

推荐答案

你的代码几乎没问题.重申一下,您需要一个用这种形式包装 http.request 的函数:

Your code is almost fine. To restate a little, you want a function that wraps http.request with this form:

function httpRequest(params, postData) {
    return new Promise(function(resolve, reject) {
        var req = http.request(params, function(res) {
            // on bad status, reject
            // on response data, cumulate it
            // on end, parse and resolve
        });
        // on request error, reject
        // if there's post data, write it to the request
        // important: end the request req.end()
    });
}

请注意添加了 paramspostData,因此可以将其用作通用请求.并注意最后一行 req.end() - 必须始终调用 - 在 OP 代码中丢失了.

Notice the addition of params and postData so this can be used as a general purpose request. And notice the last line req.end() -- which must always be called -- was missing from the OP code.

将这些更改应用于 OP 代码...

Applying those couple changes to the OP code...

function httpRequest(params, postData) {
    return new Promise(function(resolve, reject) {
        var req = http.request(params, function(res) {
            // reject on bad status
            if (res.statusCode < 200 || res.statusCode >= 300) {
                return reject(new Error('statusCode=' + res.statusCode));
            }
            // cumulate data
            var body = [];
            res.on('data', function(chunk) {
                body.push(chunk);
            });
            // resolve on end
            res.on('end', function() {
                try {
                    body = JSON.parse(Buffer.concat(body).toString());
                } catch(e) {
                    reject(e);
                }
                resolve(body);
            });
        });
        // reject on request error
        req.on('error', function(err) {
            // This is not a "Second reject", just a different sort of failure
            reject(err);
        });
        if (postData) {
            req.write(postData);
        }
        // IMPORTANT
        req.end();
    });
}

这是未经测试的,但它应该可以正常工作...

This is untested, but it should work fine...

var params = {
    host: '127.0.0.1',
    port: 4000,
    method: 'GET',
    path: '/api/v1/service'
};
// this is a get, so there's no post data

httpRequest(params).then(function(body) {
    console.log(body);
});

这些承诺也可以链接起来......

And these promises can be chained, too...

httpRequest(params).then(function(body) {
    console.log(body);
    return httpRequest(otherParams);
}).then(function(body) {
    console.log(body);
    // and so on
});

这篇关于nodejs - 如何承诺 http.request?拒绝被叫了两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-04 05:44