How do I get a JSON response from URL?
In my case, the URL is https://api.mathjs.org/v4/?expr=2*2 JSON response and then whenever someone types !test it sends the json/data from the URL.
Here is some sample code using node-fetch, I cant guarantee it will work well
const fetch = require('node-fetch')
(async () => {
const response = await fetch(`https://api.mathjs.org/v4/?expr=${encodeURIComponent(2*2)}`).then(r => r.text())
console.log(response)
})()
this logs 4.
this is a sample code as i said,
you would have to modify it to your needs, i used a iife as fetch method returns a promise
you can do:
<message>.channel.send(`the result is ${response}`)
as a example adapted from the above given code
ps: rather than using a api for math you could use mathjs package (which your using, just its the api version)
Edited: forgot of encodeURIComponent in fetch request url, or you will get a Only absolute URLs are supported error
You don't need JSON just to get the value of the query parameter from the URL. If you just need to get the number you can try it with URLSearchParams:
console.log(window.location.search); //output: '?expr=2*2'
var params = new URLSearchParams('?expr=2*2');
console.log(params.has('expr')); //output: 'true';
console.log(params.get('expr')); //output: '2*2';
you get the value from params.get('expr'));
Related
I'm currently writing tests on Cypress for an application writen in react and using redux and redux-saga. For one of my tests, I'm trying to stub a request and returning a response that the code is expecting to be an 'stringified' array by JSON so it can be parsed later.
I've tried to specify a response in the cy.route() command using JSON.stringify([desiredResponse]) but that is not working, response keeps being kind of parsed by Cypress or some other middleware before getting to the saga.
I've also tried to intercept the response in the onResponse option but seems to me like that's being executed once the response was delivered (not sure about this, made a couple of vague tests only)
// This is how my cy.route() config looks like
cy.route({
method: 'POST',
url: 'someUrl',
response: JSON.stringify([myResponse]),
});
And in my saga:
// I call the url via axios and immediately after I try to parse it
try {
const parsed = JSON.parse(response.data);
} catch (err) {
const parsed = [];
}
I would expect my response in the saga to be something like: "[myResponse]" but I got the raw array instead
Out of curiosity: have you tried avoiding to wrap [myResponse] into JSON.stringify()?
Something like
cy.route({
method: 'POST',
url: 'someUrl',
response: [myResponse],
});
Anyway: in my app, with your exact situation, my only difference with your code is that I leverage the Cypress fixtures .
Could you share a simple GitHub repo with your simplified code?
I am trying to develop an app for my fantasy baseball league to use for our draft (we some kind of quirky stuff all the major sites don't account for) - I want to pull some player data to use for the app by using MLB's API. I have been able to get the response from MLB, but can't do anything with the data after I get it back. I am trying to store the JSON into an array, and if I console.log the array as a whole, it will give me the entire chunk of data, but if I try to call the specific index value of the 1st item, it comes back as undefined.
let lastName = 'judge';
let getData = new XMLHttpRequest;
let jsonData = [];
function getPlayer () {
getData.open('GET', `http://lookup-service-
prod.mlb.com/json/named.search_player_all.bam?
sport_code='mlb'&active_sw='Y'&name_part='${lastName}%25'`, true)
getData.onload = function() {
if (this.status === 200) {
jsonData.push(JSON.parse(this.responseText));
}
}
getData.send();
console.log(jsonData);
}
When I change the above console.log to console.log(jsonData[0]) it comes back as undefined. If I go to the console and copy the property path, it displays as [""0""] - Either there has to be a better way to use the JSON data or storing it into an array is doing something abnormal that I haven't encountered before.
Thanks!
The jsonData array will be empty after calling getPlayer function because XHR loads data asynchronously.
You need to access the data in onload handler like this (also changed URL to HTTPS to avoid protocol mismatch errors in console):
let lastName = 'judge';
let getData = new XMLHttpRequest;
let jsonData = [];
function getPlayer () {
getData.open('GET', `https://lookup-service-
prod.mlb.com/json/named.search_player_all.bam?
sport_code='mlb'&active_sw='Y'&name_part='${lastName}%25'`, true)
getData.onload = function() {
if (this.status === 200) {
jsonData.push(JSON.parse(this.responseText));
// Now that we have the data...
console.log(jsonData[0]);
}
}
getData.send();
}
First answer from How to force a program to wait until an HTTP request is finished in JavaScript? question:
There is a 3rd parameter to XmlHttpRequest's open(), which aims to
indicate that you want the request to by asynchronous (and so handle
the response through an onreadystatechange handler).
So if you want it to be synchronous (i.e. wait for the answer), just
specify false for this 3rd argument.
So, you need to change last parameter in open function as below:
getData.open('GET', `http://lookup-service-
prod.mlb.com/json/named.search_player_all.bam?
sport_code='mlb'&active_sw='Y'&name_part='${lastName}%25'`, false)
But from other side, you should allow this method to act asynchronously and print response directly in onload function.
export default class App extends Component {
state = {
data: []
};
fetchData = async () => {
const response = await fetch("https://randomuser.me/api?results=5"); // Replace this with the API call to the JSON results of what you need for your app.
const json = await response.json();
this.setState({ data: json.results }); // for the randomuser json result, the format says the data is inside results section of the json.
};
So, I have this code in my App.js file for React Native. The randomuser.me is a website that just gives you random users. Using it as a test URL right now. I don't really understand what the code is doing enough to be able to use it for other parts of my project. I was able to successfully display the 5 user results but now I want to access them again and iterate through the data attribute of the state.
tldr; Can I just access the data I got from the fetch in a for loop using data[i]? Please advise. I want to see if user input matches any of the items in the response that is stored in data attribute of state.
Ok the thign that you just did, that is fetch. You retrieve data from the internet.
"https://randomuser.me/api?results=5" is an API, there is lot of different API's, and each one has it´s own way to retrieve data from. if you put "https://randomuser.me/api?results=5" in your browser, you are gonna see a JSON, some API's store data in JSON, others in an array format.
In this case, the JSON, has just one child, 'results', thats why you store "json.results".
That´s fetch. The thing that you want to do is just javascript.
Store json.results in a variable
then iterate over it
var Results = json.results //store it in a variable
for(var i = 0;i<Object.keys(Results).length;i++){ //iterate
var CurrentUser = Results[Object.keys(Results)[i]] // i use this because some JSOn have random keys
if(CurrentUser.gender==='male'){//if you meet a condition
//do whatever you want
}
}
you can also use ".map" if it´s an array
I am using fetch api to bring data from back-end and it is working as expected for me. However I am not able to figure out why there is a need of 2 then blocks in fetch call.
Fetch API uses promises and it takes a request as a parameter and return a promise that resolve to a Response Object that response object has information about the server response like status code and headers and the body of the response which is the data you want , and some of the methods on that Response Object return Promise too so you need to make another then block , methods like response.json() response.text() response.blob() , so this is why you need to then blocks , the first resolve the response from the server and the second get the data from the response .
learn more
Fetch API
javascript Promise
Using Fetch API
Fetch returns Promise (Easy article of Promise) and you need to resolve promise to access data. To resolve a promise, you need to use then()
A basic fetch example:
fetch('https://jsonplaceholder.typicode.com/todos')
.then(response => response.json())
.then(data => console.log(data, 'Data'));
In the above example, fetch returns promise, so it is resolved in
first then() where it is getting response object that is
representation of the entire HTTP response. So to extract the JSON
body content from the Response object, we need to use the json()
method, which returns a second promise that resolves with the result
of parsing the response body text as JSON. Click here for More
Detail
Here I run a fetch using online js compiler and show the output in console. Please have a look at description in the picture.
Without seeing your code, I assume the promise being returned and reconciled in the first "then" block has another asynchronous call with it's own return. For instance...
foo() //returns a promise
.then(() => { // called when "foo" resolves the promise
return bar();
})
.then(() => { // called when "bar" resolves the promise
})
.catch((err) => { //errors
});
If the first "then" block isn't returning another promise, I don't think the 2nd block will be called.
I try to use Restangular to handle calls to my restful API.
Here is my code:
var baseStories = Restangular.all('stories/all');
baseStories.getList().then(function (stories) {
console.log(stories);
})
The console.log shows the full restangularized array instead of an array of stories as I'd expect.
I use the RestangularProvider.addResponseInterceptor from the docs to unwrap the response data.
Has anyone an idea what I'm missing?
Edit:
Below is a screenshot of the console.log output from the code above. I see two stories (which is correct) and a bunch of Restangular methods. Is it possible to only get the stories?
Actually addResponseInterceptor must return restangularized element. It is written in the documentation:
https://github.com/mgonto/restangular#addresponseinterceptor
In order to get clean response you have to call plain() method on the response element:
var baseStories = Restangular.all('stories/all');
baseStories.getList().then(function (response) {
$scope.stories = response.plain();
})