'async / await for Node.js https.get
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)
})
})
}
Solution 1:[1]
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())()
Edits
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.
Solution 2:[2]
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.
Solution 3:[3]
Here is how I did it:
async myFunc = function {
let url = 'http://your.data/file';
let promise = new Promise((resolve, reject) => {
var data = '';
https.get(url, res => {
res.on('data', chunk => { data += chunk })
res.on('end', () => {
resolve(data);
})
})
});
let result = await promise; // wait until the promise resolves
doStuffWithResult(result);
};
In my case, I was fetching a .json file, so I actually used resolve(JSON.parse(data))
to return cleanely JSON object.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | |
Solution 3 | Dan Mantyla |