1

I'm trying to convert a function that returns a Promise, to one that that uses await/async (which returns an implicit Promise, I understand).

This function "wraps" a call to the https.request object, the key part being the resolve(body) that returns the response's body:

promise_it = (data) => {

  // throws FATAL
  if (!data) {throw new Error('data is missing');}

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

    let postData = JSON.stringify(data);

    let options = {
      hostname: 'httpbin.org',
      port: 443,
      path: '/post',
      method: 'POST',
      headers: {
        // 'Content-Type': 'application/json',
        // Accept: 'application/json'
          'Content-Type': 'application/x-www-form-urlencoded',
          'Content-Length': postData.length
        }
    };
    
    const https = require('https');
    let req = https.request(options, (res) => {
    
      let body = [];
      res.on('data', function(chunk) {
          body.push(chunk);
      });
      res.on('end', function() {
    
        try {
            body = JSON.parse(Buffer.concat(body).toString());
            }
        catch(e) {
            console.error(e.message)
            reject(e);
        }
    
        resolve(body);

      });
    
    });
    
    req.on('error', (e) => {
      console.error(e);
      reject(e)
    });
    
    req.write(postData);
    req.end();

  });

}
    
  try {
    data = {firstName: 'Donald', lastName: 'Duck'}
    const who = promise_it(data)
    who
      .then(r => console.info('INFO:',r))
      .catch(e => console.error('ERROR:',e));
  } 
  catch (error) {
    console.error('FATAL:',error)  
  }

The function works as expected.

I translated this into an async/await function:

async_it = async (data) => {

  if (!data) {throw new Error('data is missing');}

  let postData = JSON.stringify(data);

  let options = {
      hostname: 'httpbin.org',
      port: 443,
      path: '/post',
      method: 'POST',
      headers: {
      // 'Content-Type': 'application/json',
      // Accept: 'application/json'
          'Content-Type': 'application/x-www-form-urlencoded',
          'Content-Length': postData.length
      }
  };

  const https = require('https');

  let req = https.request(options, (res) => {

        let body = [];
        res.on('data', function(chunk) {
            body.push(chunk);
        });

        res.on('end', function() {

            try {
                body = JSON.parse(Buffer.concat(body).toString());
                // how do i return the body?
            }
            catch(e) {
                console.error('HERE:',e.message)
                throw e;
            }

        });
  });

  req.on('error', (e) => {
        console.error('THERE:',e.message)
  });

  req.write(postData);
  req.end();

}

(async () => {

  try {
    data = {firstName: 'Donald', lastName: 'Duck'}
    const who = await async_it(data)
    console.info('INFO:',who)
  } 
  catch (error) {
    console.error('FATAL:',error)  
  }

})();

But I can't seem to find a way to return the body. What am I missing?

craig
  • 25,664
  • 27
  • 119
  • 205

1 Answers1

1

Unfortunately https.request uses the "last parameter callback" Node.js style, so there is no possibility to use it as-is with async/await.

You could make a wrapper like in nodejs - How to promisify http.request? reject got called two times for example, and then you can use it like:

try {
  const body = await httpsRequest(options, postData);
  return body;
} catch (e) {
  console.error('THERE:',e.message);
}

But the mentioned wrapper is not much less than your current one (Promise version).

ghybs
  • 47,565
  • 6
  • 74
  • 99