node.jsasync-awaithttp2getmethod

In NodeJS, how do I await the response of the http2 client library GET call?


I'm using the http2 client package with nodeJS. I want to execute a simple get request, and await the response from the server. So far I have

import * as http2 from "http2";
...
 const clientSession = http2.connect(rootDomain);
  ...
  const req = clientSession.request({ ':method': 'GET', ':path': path });
  let data = '';
  req.on('response', (responseHeaders) => {
    // do something with the headers
  });
  req.on('data', (chunk) => {
    data += chunk;
    console.log("chunk:" + chunk);
  });
  req.on('end', () => {
    console.log("data:" + data);
    console.log("end!");
    clientSession.destroy();
  });
  process.exit(0);

But what I"m not able to figure out is how to do I await the response of the request before exiting? Right now the code flies through to the process.exit line and I can't see a way to block until the request is done.


Solution

  • If you want to await it, then you have to encapsulate it into a function that returns a promise and you can then use await on that promise. Here's one way to do that:

    import * as http2 from "http2";
    ...
    
    function getData(path) {
        return new Promise((resolve, reject) => {
            const clientSession = http2.connect(rootDomain);
            const req = clientSession.request({ ':method': 'GET', ':path': path });
            let data = '';
            req.on('response', (responseHeaders) => {
                // do something with the headers
            });
            req.on('data', (chunk) => {
                data += chunk;
                console.log("chunk:" + chunk);
            });
            req.on('end', () => {
                console.log("data:" + data);
                console.log("end!");
                clientSession.destroy();
                resolve(data);
            });
            req.on('error', (err) => {
                clientSession.destroy();
                reject(err);
            });
        });
    }
    
    async function run() {
        let data = await getData(path);
    
        // do something with data here
    
    }
    
    run().then(() => {
        process.exit(0);
    }).catch(err => {
        console.log(err);
        process.exit(1);
    });
    

    The other way to do this is to use a higher level http library that does much of this work for you. Here's an example using the got module:

    import got from 'got';
    
    async function run() {
        let data = await got(url, {http2: true});
    
        // do something with data here
    
    }
    

    In this case, the got() module already supports http2 for you (if you specify that option), already collects the whole response for you and already supports promises (all the things your code needed to add in your original version).

    Note, the GET method is the default method which is why it is not necessary to specify it here.