nodejs-如何使http.request合理化?拒绝被叫了两次 [英] nodejs - How to promisify http.request? reject got called two times
问题描述
我正在尝试将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()
});
}
请注意,添加了params
和postData
,因此可以将其用作通用请求. 并注意最后一行 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.
将这些更改应用到操作码...
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合理化?拒绝被叫了两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!