Promise-wrapping http 请求无法结束

Promise-wrapping http request cannot be ended

const http = require("http");

async function sendRequest(url) {
    url = new URL(url);
    const requestDetails = {
        'hostname': url.hostname,
        'port': url.port || 80,
        'path': url.pathname,
        'method': 'GET'
    };

    const req = await new Promise((resolve, reject) => {
        const request = http.request(requestDetails, response => {
            const status = response.statusCode;
            if (status === 200 || status === 201) {
                console.log("SUCCESS");
                resolve(request);
            } else {
                console.log("ERROR");
                reject(`Status code returned was ${status}`);
            }
        });
    });

    req.end();
}

sendRequest('http://httpbin.org/get');

当 req.end() 在 promise 中时有效,但在传递请求后执行 req.end(),控制台只是保持没有任何响应。我试图通过中间变量比较“req === request”,它返回 true。为什么移出 end() 不起作用?这两个对象不应该一样吗?

您应该将 request.end 调用移到 promise 中,否则它只会调用更新的,因为您将等待更新的 promise 解决,因为请求未发送。

此外,如果请求对象发出错误事件,您应该拒绝承诺。

req.end() 的目的是完成请求。我们可能会小心,如果任何正文部分未发送或可能正在进行中,它将在流中刷新它们,或者如果任何请求被分块,这将发送到终止。

我以稍微不同且更简洁的方式实现了您的相同代码。下面的方法可能有助于为多个 api 重用相同的代码。

const http = require("http");

/**
 * @description call the http request
 */
async function doHttp(requestDetails){  
    return new Promise((resolve, reject)=>{
      http.request(requestDetails, response => {
        const status = response.statusCode;
        response.setEncoding("utf-8");
          if (status === 200 || status === 201) {
              console.log("SUCCESS");                
              response.on('data', data => {
                return resolve(data);
              });
          } else {
              console.error("ERROR");
              return reject(new Error("emptyData"));
          }     
        }).on('error', (err) => {
        // Catch the error if occured in request
        console.error(`problem with request: ${e.message}`);
        return reject(err);
      }).end();
    });
}

/**
 * @description sending the request
 */
async function doSend(url) {
    url = new URL(url);
    const requestDetails = {
        'hostname': url.hostname,
        'port': url.port || 80,
        'path': url.pathname,
        'method': 'GET'
    };
    const data = await doHttp(requestDetails)
    console.log(data);
}

doSend('http://httpbin.org/get');

最后,我们可以说需要 req.end() 才能完成任何请求。这完全取决于我们,我们如何实现一个方法。

另一种解决方案可能是本机 https 模块,例如 Axiossuperagent , got, node-fetch.他们在原生 nodejs 代码上提供了一个包装器,可以帮助我们控制处理错误和响应。