Well I had a bit problems
function getId(username){
const https = require("https")
let id = ""
let data = ``
https.get(`https://api.roblox.com/users/get-by-username?username=${username}`, (response) =>{
response.on('data', (chunk) => {
data += chunk;
})
response.on('end', () =>{
if(data){
id = JSON.parse(data).Id
}
})
})
.on('error', (error) => {
console.log(error)
})
return id
}
So my goal here to use getId("IHZAQSTORM33") and expected result, it will return user id (1684676332). but instead, it give me (""). It give me a colons
yes I'm trying to connect to roblox api.
Use promise to return the response object as shown in the code.
You can also refer to link for the comment by nkron:
Where is body in a nodejs http.get response?
function getId(username) {
const https = require('https');
let id = '';
let data = '';
const url = `https://api.roblox.com/users/get-by-username?username=${username}`;
return new Promise((resolve, reject) => {
https
.get(url, (response) => {
response.on('data', (chunk) => {
data += chunk;
});
response.on('end', () => {
resolve(data);
});
})
.on('error', reject);
});
//return id
};
(async () => {
const responseObject = await getId('IHZAQSTORM33');
})();
For more on async and await, refer this link:
await is only valid in async function
Related
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.
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.
response = await new Promise(async (resolve, reject)=> {
let data = '';
req.on('data', async (chunk) => {
data += chunk;
resolve(JSON.parse(data));
});
});
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)
})
})
}
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) => {
let data = ''
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.
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.
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.
Yes, I have seen many other questions and answers. I know I need to use a callback response. However, I still don't get how to do this particular example. Most examples involve a callback response that logs something or the post has hundreds of different answers.
How do I return the request response from getPageData?
var url = "myurl";
var name = await getPageData(url);
// wait until I get name and then do stuff with name
function getPageData(url)
{
const https = require('https');
https.get(url, (resp) => {
let data = '';
resp.on('data', (chunk) => {
data += chunk;
});
resp.on('end', () => {
var name = JSON.parse(data);
// what do I do here to get name out?
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
}
await can only be used in async functions. You can however return a promise from getPageData and "await" using chained then:
Use the Promise object:
const https = require('https');
var url = "myurl";
var name;
getPageData(url)
.then(data => { name = data; /*This is the scope in which you would use name*/ })
.catch(err => { console.log('Error occured', err); });
async function getPageData(url) {
return new Promise((resolve, reject) => {
https
.get(url, resp => {
let data = '';
resp.on('data', chunk => {
data += chunk;
});
resp.on('end', () => {
const name = JSON.parse(data);
// what do I do here to get name out?
resolve(name);
});
})
.on('error', err => {
console.log(`Error: ${err.message}`);
reject(err);
});
});
}
The higher level solution here is to use a module for making http requests that already supported promises. You can see a list of many of them here. My favorite from that list is got() and you can use it to solve your problem like this:
function getPageData(url) {
return got(url);
}
// can only use await inside a function declared as async
async function someFunction() {
try {
let name = await getPageData(url);
console.log(name);
} catch(e) {
console.log(e);
}
}
The got() library does a whole bunch of things for you.
It is entirely based on promises so you can directly use await on the promise it returns.
It collects the whole response for you (you don't have to write your own code to do that).
If the response is JSON, it automatically parses that for you and resolves to the parsed Javascript object.
It automatically detects http or https URL and uses the right low level module.
And, it has dozens of other useful features (not needed in this example).
Or, if you want the lower level solution where you make your own promisified function for doing an https request, you can do this:
const https = require('https');
// can only use await inside a function declared as async
async function someFunction() {
const url = "myurl";
try {
let name = await getPageData(url);
console.log(name);
} catch(e) {
console.log(e);
}
}
function getPageData(url) {
return new Promise((resolve, reject) => {
https.get(url, (resp) => {
let data = '';
resp.on('data', (chunk) => {
data += chunk;
});
resp.on('end', () => {
try {
const name = JSON.parse(data);
resolve(name);
} catch(e) {
// JSON parsing error
reject(e);
}
});
}).on("error", (err) => {
console.log("Error: " + err.message);
reject(err);
});
}).on('error', (err) => {
console.log("Error: " + err.message);
reject(err);
});
}
As part of a program I am writing, I'd like to have a helper function that shortens some long URLs that are created. I found this package:
and am attempting to change the code so that it simply stores the string in a variable and returns it. I am having some issues with scope. the variable resData is never actually updated and return is always an empty string. How can I get this returned string into the global variable and return it? Thanks
var http = require("http")
module.exports = {
shorten: function(url) {
var resData = ''
http.get('[tinyurl api endpoint]' + encodeURIComponent(url), (res) => {
res.setEncoding('utf8')
res.on('data', (chunk) => {resData += chunk})
res.on('end', () => {
resData = resData.toString()
//this contains the link, and can be console.logged
})
}).on('error', (e) => {
console.log(e)
})
return resData //returns empty string
}
};
do this
var http = require("http")
module.exports = {
shorten: function(url,cb) {
var resData = ''
http.get('[tinyurl api endpoint]' + encodeURIComponent(url), (res) => {
res.setEncoding('utf8')
res.on('data', (chunk) => {resData += chunk})
res.on('end', () => {
resData = resData.toString()
//this contains the link, and can be console.logged
cb(null,resData) //<----- use callback (thanks robertklep)
})
}).on('error', (e) => {
console.log(e)
})
//--> return resData //returns empty string as node is non-blocking io, this line will be executed before http response is received
}
};
//index.js
var http = require('./path/to/that/module')
http.shorten(url,function(error,result){ console.log(result) })
Try to use with callback function
shorten: function(url,callback) {
var resData = ''
http.get('[tinyurl api endpoint]' + encodeURIComponent(url), (res) => {
res.setEncoding('utf8')
res.on('data', (chunk) => {resData += chunk})
res.on('end', () => {
resData = resData.toString()
//this contains the link, and can be console.logged
callback(null,resData); //<----here
})
}).on('error', (e) => {
console.error(e);
callback(e,null); //<----- and here
})
}
I'm trying to read the content from a URL with Node.js but all I seem to get are a bunch of bytes. I'm obviously doing something wrong but I'm not sure what. This is the code I currently have:
var http = require('http');
var client = http.createClient(80, "google.com");
request = client.request();
request.on('response', function( res ) {
res.on('data', function( data ) {
console.log( data );
} );
} );
request.end();
Any insight would be greatly appreciated.
try using the on error event of the client to find the issue.
var http = require('http');
var options = {
host: 'google.com',
path: '/'
}
var request = http.request(options, function (res) {
var data = '';
res.on('data', function (chunk) {
data += chunk;
});
res.on('end', function () {
console.log(data);
});
});
request.on('error', function (e) {
console.log(e.message);
});
request.end();
HTTP and HTTPS:
const getScript = (url) => {
return new Promise((resolve, reject) => {
const http = require('http'),
https = require('https');
let client = http;
if (url.toString().indexOf("https") === 0) {
client = https;
}
client.get(url, (resp) => {
let data = '';
// A chunk of data has been recieved.
resp.on('data', (chunk) => {
data += chunk;
});
// The whole response has been received. Print out the result.
resp.on('end', () => {
resolve(data);
});
}).on("error", (err) => {
reject(err);
});
});
};
(async (url) => {
console.log(await getScript(url));
})('https://sidanmor.com/');
the data object is a buffer of bytes. Simply call .toString() to get human-readable code:
console.log( data.toString() );
reference: Node.js buffers
A slightly modified version of #sidanmor 's code. The main point is, not every webpage is purely ASCII, user should be able to handle the decoding manually (even encode into base64)
function httpGet(url) {
return new Promise((resolve, reject) => {
const http = require('http'),
https = require('https');
let client = http;
if (url.toString().indexOf("https") === 0) {
client = https;
}
client.get(url, (resp) => {
let chunks = [];
// A chunk of data has been recieved.
resp.on('data', (chunk) => {
chunks.push(chunk);
});
// The whole response has been received. Print out the result.
resp.on('end', () => {
resolve(Buffer.concat(chunks));
});
}).on("error", (err) => {
reject(err);
});
});
}
(async(url) => {
var buf = await httpGet(url);
console.log(buf.toString('utf-8'));
})('https://httpbin.org/headers');