I'm trying to simplify code with async / await
But have problems making https.get
with async / await structure.
I am aware of how to do this with third-party modules but prefer the native node.js https
module.
Below code doesn't work for me:
async function get_page() {
const https = require('https')
const url = 'https://example.com'
const util = require('util')
const https_get = util.promisify(https.get)
const data = await https_get(url)
do_awesome_things_with_data(data)
}
This code working fine:
function get_page() {
const https = require('https')
const url = 'https://example.com'
let data = ''
https.get(url, res => {
res.on('data', chunk => { data += chunk })
res.on('end', () => {
do_awesome_things_with_data(data)
})
})
}
XMLHttpRequest supports both synchronous and asynchronous communications.
Async functions are available natively in Node and are denoted by the async keyword in their declaration. They always return a promise, even if you don't explicitly write them to do so. Also, the await keyword is only available inside async functions at the moment – it cannot be used in the global scope.
With version 17.5, Node. js has made experimental support for the Fetch API available. Since then, we no longer need to install a third-party library to create server-side JavaScript code that utilizes the Fetch API.
https.get
doesn't return something that can be promisified as the signature of the callback doesn't match (err, value)
, so you can't await it.
However, you can wrap the https.get
call within a Promise, like so, then await when calling get_page
const https = require('https')
async function get_page() {
const url = 'https://example.com'
return new Promise((resolve) => {
https.get(url, res => {
res.on('data', chunk => { data += chunk })
res.on('end', () => {
resolve(do_awesome_things_with_data(data));
})
})
})
}
// usage
(async () => await get_page())()
I've updated my answer to include the note of https.get
not being able to be promisified and moved the require('https')
outside of the function call.
Instead of promisify, roll your own function, or use a 3rd party library. Promisify cannot wrap what https.get
returns.
// generic promise method for https
const requestPromise = ((urlOptions, data) => {
return new Promise((resolve, reject) => {
const req = https.request(urlOptions,
(res) => {
let body = '';
res.on('data', (chunk) => (body += chunk.toString()));
res.on('error', reject);
res.on('end', () => {
if (res.statusCode >= 200 && res.statusCode <= 299) {
resolve({statusCode: res.statusCode, headers: res.headers, body: body});
} else {
reject('Request failed. status: ' + res.statusCode + ', body: ' + body);
}
});
});
req.on('error', reject);
req.write(data, 'binary');
req.end();
});
});
Then call it like this:
async function get_page() {
const url = 'https://example.com'
const data = await requestPromise({url, method:'GET'})
do_awesome_things_with_data(data)
}
Or simply use a library such as axios
to return a native promise, and also handle additional boilerplate cases.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With