0
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');

It works when req.end() is inside the promise, but after passing the request out then execute req.end(), the console is just holding without any response. I tried to compare "req === request" by a middle variable, it returned true. Why doesn't moving end() out work? Shouldn't these two object the same?

2 Answers2

0

You should move the request.end call inside the promise otherwise it just newer gets called because you will be waiting for a promise that is newer resolved because the request is not send.

Also you should reject the promise in case request object emits error event.

Ayzrian
  • 2,279
  • 1
  • 7
  • 14
0

The purpose of the req.end() is to finish the request. We might be cautious that if any body part is unsent or might in progress, it will flush them in the stream, or if any request is chunked, this will send to terminating.

I have implemented your same code in a bit different and cleaner way. Below way might help to reuse the same code for multiple apis.

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');

At last, we could say req.end() is required to finish up any request. It completely depends on us, how we can implement a method.

An alternate solution might be this native https module is such as Axios, superagent, got, node-fetch. They provide a wrapper over the native nodejs code which might help us to control to handle an error and response.

Dipak
  • 2,248
  • 4
  • 22
  • 55