Node.js nodejs-如何提示http.request?我打了两次电话

Node.js nodejs-如何提示http.request?我打了两次电话,node.js,promise,httprequest,Node.js,Promise,Httprequest,我正在尝试将http.request包装成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.statusCod

我正在尝试将
http.request
包装成
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);
});
新承诺(功能(解析、拒绝){
var req=http.request({
主持人:“127.0.0.1”,
港口:4000,
方法:“GET”,
路径:'/api/v1/service'
},功能(res){
如果(res.statusCode<200 | | res.statusCode>=300){
//第一次拒绝
拒绝(新错误('statusCode='+res.statusCode));
返回;
}
变量体=[];
res.on('data',函数(块){
推(块);
});
res.on('end',function(){
试一试{
body=JSON.parse(Buffer.concat(body.toString());
}捕获(e){
拒绝(e);
返回;
}
决议(机构);
});
});
请求开启('error',函数(err){
//第二次拒绝
拒绝(错误);
});
请求写入(“测试”);
}).then(功能(数据){
控制台日志(数据);
}).catch(函数(err){
控制台日志(err);
});
如果我从远程服务器接收到errornous
statusCode
,它将调用First reject并在一段时间后调用Second reject。如何正确地使其只调用单个拒绝(我认为在这种情况下,第一次拒绝是正确的拒绝)?我想我需要自己关闭
res
,但是
ClientResponse
对象上没有
close()
方法

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

使用bluebird api更容易,您可以请求模块并使用请求函数async作为承诺本身,或者您可以选择使用模块,这使您不必创建承诺,而是使用已经使用承诺封装模块的and对象,下面是一个例子:

var rp = require('request-promise');

rp({host: '127.0.0.1',
    port: 4000,
    method: 'GET',
    path: '/api/v1/service'})
    .then(function (parsedBody) {
        // GET succeeded... 
    })
    .catch(function (err) {
        // GET failed... 
    });

你的代码几乎是好的。要重申一点,您需要一个用以下表单包装http.request的函数:

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()

将这些更改应用于操作代码

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();
    });
}
这些承诺也可能被束缚住

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

我知道这个问题由来已久,但这个答案实际上启发了我编写一个轻量级promisified HTTP客户端的现代版本。以下是一个新版本:

  • 使用最新的JavaScript语法
  • 验证输入
  • 支持多种方法
  • 易于扩展HTTPS支持
  • 将让客户决定如何处理响应代码
  • 还将让客户机决定如何处理非JSON实体
代码如下:

function httpRequest(method, url, body = null) {
    if (!['get', 'post', 'head'].includes(method)) {
        throw new Error(`Invalid method: ${method}`);
    }

    let urlObject;

    try {
        urlObject = new URL(url);
    } catch (error) {
        throw new Error(`Invalid url ${url}`);
    }

    if (body && method !== 'post') {
        throw new Error(`Invalid use of the body parameter while using the ${method.toUpperCase()} method.`);
    }

    let options = {
        method: method.toUpperCase(),
        hostname: urlObject.hostname,
        port: urlObject.port,
        path: urlObject.pathname
    };

    if (body) {
        options.headers = {'Content-Length':Buffer.byteLength(body)};
    }

    return new Promise((resolve, reject) => {

        const clientRequest = http.request(options, incomingMessage => {

            // Response object.
            let response = {
                statusCode: incomingMessage.statusCode,
                headers: incomingMessage.headers,
                body: []
            };

            // Collect response body data.
            incomingMessage.on('data', chunk => {
                response.body.push(chunk);
            });

            // Resolve on end.
            incomingMessage.on('end', () => {
                if (response.body.length) {

                    response.body = response.body.join();

                    try {
                        response.body = JSON.parse(response.body);
                    } catch (error) {
                        // Silently fail if response is not JSON.
                    }
                }

                resolve(response);
            });
        });
        
        // Reject on request error.
        clientRequest.on('error', error => {
            reject(error);
        });

        // Write request body if present.
        if (body) {
            clientRequest.write(body);
        }

        // Close HTTP connection.
        clientRequest.end();
    });
}
希望这有帮助

const request = require('request');

async function getRequest() {
  const options = {
    url: 'http://example.com',
    headers: {
      'Authorization': 'Bearer xxx'
    }
  };

  return new Promise((resolve, reject) => {
    return request(options, (error, response, body) => {
      if (!error && response.statusCode == 200) {
        const json = JSON.parse(body);
        return resolve(json);
      } else {
        return reject(error);
      }
    });
  })
}

还有其他方法,但在这里您可以找到一种简单的方法,将http.request作为承诺或异步/等待类型

这是一个工作示例代码:

var http=require('http');
函数requestAsync(名称){
返回新承诺((解决、拒绝)=>{
var post_选项={
主持人:“restcountries.eu”,
端口:'80',
路径:`/rest/v2/name/${name}`,
方法:“GET”,
标题:{
“内容类型”:“应用程序/json”
}
};
让post_req=http.request(post_选项,(res)=>{
res.setEncoding('utf8');
res.on('数据',(块)=>{
解析(块);
});
res.on(“错误”,“错误)=>{
拒绝(错误);
});
});
post_请求写入(“测试”);
post_请求结束();
});
}
//调用请求函数
//:1-作为承诺
requestAsync(“印度”)。然后(countryDetails=>{
console.log(countryDetails);
}).catch((错误)=>{
控制台日志(err);
}); 
//:2-等待
让countryDetails=Wait requestAsync(“印度”);

在阅读了所有这些和一些文章之后,我想我应该发布一种处理http和https的“通用”解决方案:

consthttp=require(“http”);
const https=require(“https”);
const url_obj=require(“url”);
const request=async(url\u string,method=“GET”,postData=null)=>{
const url=url\u obj.parse(url\u字符串);
const lib=url.protocol==“https:”?https:http;
常量参数={
方法:方法,,
主机:url.host,
端口:url.port | | url.protocol==“https:”?443:80,
路径:url.path | |“/”
};
返回新承诺((解决、拒绝)=>{
const req=lib.request(参数,res=>{
如果(res.statusCode<200 | | res.statusCode>=300){
返回拒绝(新错误(`Status Code:${res.statusCode}`));
}
常量数据=[];
res.on(“数据”,chunk=>{
数据推送(块);
});
res.on(“end”,()=>resolve(Buffer.concat(data.toString()));
});
请求打开(“错误”,拒绝);
if(postData){
请求写入(postData);
}
请求结束();
});
}
您可以这样使用:

request(“google.com”).then(res=>console.log(res)).catch(err=>console.log(err))

这本书的灵感来源于,但它用内置的api取代了拙劣的url解析。

我的老板或工作不需要解决方案,我是PHP/Python开发人员。相反,我需要理解NodeJS外部http请求的剖析,并学习如何提出建议。我试着看了一下request-promise-core,但代码不可读,我什么都没学到。我学到的一件好事是,承诺不能被拒绝两次:)第二次拒绝将被忽略。但仍然不明白如何在承诺中转变严格模式,所以第二次拒绝将抛出错误,而不是被忽略。@happy_marmoset-承诺一旦被拒绝,就完成了。如果您希望它报告第二个错误,那么您将领导wro
const request = require('request');

async function getRequest() {
  const options = {
    url: 'http://example.com',
    headers: {
      'Authorization': 'Bearer xxx'
    }
  };

  return new Promise((resolve, reject) => {
    return request(options, (error, response, body) => {
      if (!error && response.statusCode == 200) {
        const json = JSON.parse(body);
        return resolve(json);
      } else {
        return reject(error);
      }
    });
  })
}