问题描述
我正在尝试将 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.
将这些更改应用于 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?拒绝被叫了两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!