I have a GWT app in which I have to include an JS function. So I am using the native interface to use the JS function in my JAVA code.
This is my JS function
function fetchToken() {
return fetch(URL, { method: "POST" })
.then(function(response) {
console.log(response.json());
return response.json();
})
.then(function(data) {
return data.secret;
});
}
But the problem with this is when I receive the Promise response via response.json(), it is still in pending state, so it never goes to line 6. I tried using async but it seems like GWT does not support using async/await.
Is there a way I can use async in GWT or any other way to use JS in GWT other than native interface in which I do not face this issue?
function makeAsyncRequest() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
// Request was successful. Do something with the response.
console.log(xhr.responseText);
}
};
xhr.open("GET", "http://example.com/api/endpoint", true);
xhr.send();
}
I got my mistake, I used response.json() twice in my code, once to log and once to return. I realised I can only use it once in my code. Removing the log fixed my code.
function fetchToken() {
return fetch(URL, { method: "POST" })
.then(function(response) {
return response.json();
})
.then(function(data) {
return data.secret;
});
}
Related
I open the Hackerrank example test and play around with methods one might use to make an AJAX call. XMLHttpReq, fetch, etc. None of them work; XHR and fetch methods are unavailable.
First fetch:
async function myFetch() {
let response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
let data = await response.json();
console.log(data);
}
Hackerrank throws an error because fetch is not a function. I also tried window.fetch and global.fetch to no avail.
I tried XHR:
function myXHR() {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState === 4 && this.status === 200) {
console.log(this.responseText);
// or JSON.parse(this.responseText);
}
};
xmlhttp.open('GET', 'https://jsonplaceholder.typicode.com/todos/1');
xmlhttp.send();
}
Hackerrank says XMLHttpRequest is not defined.
Hackerrank is executing Node.JS code, that explains why XHR isn't available, I have to require myself perhaps. Except I can't npm install anything, all I have access to is their little IDE.
How do you make an AJAX call in this platform with JavaScript?
I've passed the HackerRank REST API certification and had the same issue. HackerRank uses a NodeJs environnement to run you code (it's said in the langage selection), so neither XMLHttpRequest nor fetch are available ( as these are Browser only ).
I suggest you use the request npm package, HackerRank allows you to require it.
One downside is that request doesn't support Promises & Async/Await unless you import other packages (which HackerRank doesn't seem to recognize).
Here's what I used :
const request = require('request');
function myFetch(url) {
return new Promise((resolve, reject) => {
request(url, function (error, response, body) {
if(error) reject(error)
else resolve(body)
});
});
}
Note : request package has been recently deprecated, but it will still work well for your use case.
I have given a test in HackerRank recently and I have used the node.js native module for http/https to fetch data from an API. As you can use this without requiring any external libraries.
also, if you need to create promises you can create your own wrapping over the https implementation.
Try using this:
async function fetchData(url) {
const https = require('https');
return new Promise((resolve, reject) => {
https.get(url, (response) => {
let data = '';
response.on('data', (stream) => {
data += stream;
})
response.on('end', () => {
const resolvedData = JSON.parse(data);
resolve(data);
})
}).on('error', (err) => {
reject(err);
})
});
}
async function showData() {
const data = await fetchData('https://jsonmock.hackerrank.com/api/movies?Year=2000');
console.log(data);
}
showData();
this can solve your problem in HackerRank. This example is only given for a get request. For all other Methods please try using the options from https module of Node.js.
Hackerrank currently uses node version 14.x.xx which comes with axios.
All you have to do is scroll to the top and import or require axios, then you can make use of axios.get() or axios.post() as the case may be.
Hackerrank currently uses node version 14.x.xx which comes with Axios
Example for get call:
a) const axios = require('axios');
b) let response = await axios.get('URL here');
In the same way, you can use all HTTP Methods.
let url = 'https://someurl.com/api/article_users?username=username';
const https = require('https');
https.get(url, (res) => {
console.log('statusCode:', res.statusCode);
console.log('headers:', res.headers);
res.on('data', (d) => {
process.stdout.write(d);
});
}).on('error', (e) => {
console.error(e);
});
This worked for me.
In my vanilla js project I have a following chain of promises:
API.POST({link to login endpoint}, "email=foo&pass=bar")
.then(() => User.initiate(API))
.then(() => console.log(User.name || 'wat'));
API object has POST and GET methods both looking the same, except the request type:
GET (url, params = null) {
console.log("GET start");
return new Promise((resolve,reject) => {
this._request('GET', url, params)
.then(result => resolve(result));
});
}
POST (url, params = null) {
return new Promise((resolve,reject) => {
this._request('POST', url, params)
.then(result => resolve(result));
});
}
... and a _request method responsible for sending the request:
_request (type, url, params = null) {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.open(type,url,true);
xhr.withCredentials = true;
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=UTF-8");
xhr.onload = function(){
if (this.status == 200) {
console.log(type + ' done');
resolve(this.response);
} else {
reject(this.response._status.code);
}
};
xhr.send(params);
});
}
App's User object provides "initiate" method that calls the API to check if user is logged in. With positive response API returns an _embedded.user object, that in the next step is used to populate app's User properties:
initiate(API) {
API.GET({link to authorization check endpoint})
.then(authData => this.regenerate(authData._embedded.user));
},
regenerate(userData) {
this.name = userData.name;
// and so on, for each User property
return new Promise((resolve,reject) => {
resolve(this);
});
}
What I expect to happen is:
Request to API to log in is sent (this is just to skip the actual logging in process that is irrelevant to the current work)
API returns cookie allowing for further testing as an logged user
Request to API is sent to ask if user is authenticated
API responds with confirmation and _embedded.user object
App's User object's properties get populated by data from API response
User.name is logged in console
Step 6 though fires between steps 3. and 4. and I can't find the reason why. My console looks following (notice the console.logs in API object code above):
POST done
GET start
wut
GET done
What can be the reason of this? Thanks in advance.
Missing a return in initiate()
initiate(API) {
return API.GET({link to authorization check endpoint})
//^^ return the promise
.then(authData => this.regenerate(authData._embedded.user));
}
Also using a promise anti-pattern in your GET and POST methods. There is no need to create a new promise in each since _request() already returns a promise
All you need is:
GET (url, params = null) {
return this._request('GET', url, params);
}
POST (url, params = null) {
return this._request('POST', url, params);
}
For more detailed explanation see What is the explicit promise construction antipattern and how do I avoid it?
Rather than using XMLHttpRequest you may also want to look at using the more recent fetch() API which has built in promises and better error handling
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 months ago.
I am trying to use a Node.JS application to make and receive API requests. It does a get request to another server using Axios with data it receives from an API call it receives. The second snippet is when the script returns the data from the call in. It will actually take it and write to the console, but it won't send it back in the second API.
function axiosTest() {
axios.get(url)
.then(function (response) {
console.log(response.data);
// I need this data here ^^
return response.data;
})
.catch(function (error) {
console.log(error);
});
}
...
axiosTestResult = axiosTest();
response.json({message: "Request received!", data: axiosTestResult});
I'm aware this is wrong, I'm just trying to find a way to make it work. The only way I can seem to get data out of it is through console.log, which isn't helpful in my situation.
The issue is that the original axiosTest() function isn't returning the promise. Here's an extended explanation for clarity:
function axiosTest() {
// create a promise for the axios request
const promise = axios.get(url)
// using .then, create a new promise which extracts the data
const dataPromise = promise.then((response) => response.data)
// return it
return dataPromise
}
// now we can use that data from the outside!
axiosTest()
.then(data => {
response.json({ message: 'Request received!', data })
})
.catch(err => console.log(err))
The function can be written more succinctly:
function axiosTest() {
return axios.get(url).then(response => response.data)
}
Or with async/await:
async function axiosTest() {
const response = await axios.get(url)
return response.data
}
Guide on using promises
Info on async functions
I know this post is old. But i have seen several attempts of guys trying to answer using async and await but getting it wrong. This should clear it up for any new references
UPDATE: May 2022
This answer is still having lots of interest and have updated it to use arrow functions
const axiosTest = async () {
try {
const {data:response} = await axios.get(url) //use data destructuring to get data from the promise object
return response
}
catch (error) {
console.log(error);
}
}
you can populate the data you want with a simple callback function,
let's say we have a list named lst that we want to populate,
we have a function that pupulates pupulates list,
const lst = [];
const populateData = (data) => {lst.push(data)}
now we can pass the callback function to the function which is making the axios call and we can pupulate the list when we get data from response.
now we make our function that makes the request and pass populateData as a callback function.
function axiosTest (populateData) {
axios.get(url)
.then(function(response){
populateData(response.data);
})
.catch(function(error){
console.log(error);
});
}
The axios library creates a Promise() object. Promise is a built-in object in JavaScript ES6. When this object is instantiated using the new keyword, it takes a function as an argument. This single function in turn takes two arguments, each of which are also functions — resolve and reject.
Promises execute the client side code and, due to cool Javascript asynchronous flow, could eventually resolve one or two things, that resolution (generally considered to be a semantically equivalent to a Promise's success), or that rejection (widely considered to be an erroneous resolution). For instance, we can hold a reference to some Promise object which comprises a function that will eventually return a response object (that would be contained in the Promise object). So one way we could use such a promise is wait for the promise to resolve to some kind of response.
You might raise we don't want to be waiting seconds or so for our API to return a call! We want our UI to be able to do things while waiting for the API response. Failing that we would have a very slow user interface. So how do we handle this problem?
Well a Promise is asynchronous. In a standard implementation of engines responsible for executing Javascript code (such as Node, or the common browser) it will resolve in another process while we don't know in advance what the result of the promise will be. A usual strategy is to then send our functions (i.e. a React setState function for a class) to the promise, resolved depending on some kind of condition (dependent on our choice of library). This will result in our local Javascript objects being updated based on promise resolution. So instead of getters and setters (in traditional OOP) you can think of functions that you might send to your asynchronous methods.
I'll use Fetch in this example so you can try to understand what's going on in the promise and see if you can replicate my ideas within your axios code. Fetch is basically similar to axios without the innate JSON conversion, and has a different flow for resolving promises (which you should refer to the axios documentation to learn).
GetCache.js
const base_endpoint = BaseEndpoint + "cache/";
// Default function is going to take a selection, date, and a callback to execute.
// We're going to call the base endpoint and selection string passed to the original function.
// This will make our endpoint.
export default (selection, date, callback) => {
fetch(base_endpoint + selection + "/" + date)
// If the response is not within a 500 (according to Fetch docs) our promise object
// will _eventually_ resolve to a response.
.then(res => {
// Lets check the status of the response to make sure it's good.
if (res.status >= 400 && res.status < 600) {
throw new Error("Bad response");
}
// Let's also check the headers to make sure that the server "reckons" its serving
//up json
if (!res.headers.get("content-type").includes("application/json")) {
throw new TypeError("Response not JSON");
}
return res.json();
})
// Fulfilling these conditions lets return the data. But how do we get it out of the promise?
.then(data => {
// Using the function we passed to our original function silly! Since we've error
// handled above, we're ready to pass the response data as a callback.
callback(data);
})
// Fetch's promise will throw an error by default if the webserver returns a 500
// response (as notified by the response code in the HTTP header).
.catch(err => console.error(err));
};
Now we've written our GetCache method, lets see what it looks like to update a React component's state as an example...
Some React Component.jsx
// Make sure you import GetCache from GetCache.js!
resolveData() {
const { mySelection, date } = this.state; // We could also use props or pass to the function to acquire our selection and date.
const setData = data => {
this.setState({
data: data,
loading: false
// We could set loading to true and display a wee spinner
// while waiting for our response data,
// or rely on the local state of data being null.
});
};
GetCache("mySelelection", date, setData);
}
Ultimately, you don't "return" data as such, I mean you can but it's more idiomatic to change your way of thinking... Now we are sending data to asynchronous methods.
Happy Coding!
axiosTest() needs to return axios.get, which in turn returns a Promise.
From there, then can be used to execute a function when said Promise resolves.
See Promise for more info.
Alternatively, await can be used from within the scope of some async function.
// Dummy Url.
const url = 'https://jsonplaceholder.typicode.com/posts/1'
// Axios Test.
const axiosTest = axios.get
// Axios Test Data.
axiosTest(url).then(function(axiosTestResult) {
console.log('response.JSON:', {
message: 'Request received',
data: axiosTestResult.data
})
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.js"></script>
IMO extremely important rule of thumb for your client side js code is to keep separated the data handling and ui building logic into different funcs, which is also valid for axios data fetching ... in this way your control flow and error handlings will be much more simple and easier to manage, as it could be seen from this
ok fetch
and this
NOK fetch
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
function getUrlParams (){
var url_params = new URLSearchParams();
if( window.location.toString().indexOf("?") != -1) {
var href_part = window.location.search.split('?')[1]
href_part.replace(/([^=&]+)=([^&]*)/g,
function(m, key, value) {
var attr = decodeURIComponent(key)
var val = decodeURIComponent(value)
url_params.append(attr,val);
});
}
// for(var pair of url_params.entries()) { consolas.log(pair[0]+ '->'+ pair[1]); }
return url_params ;
}
function getServerData (url, urlParams ){
if ( typeof url_params == "undefined" ) { urlParams = getUrlParams() }
return axios.get(url , { params: urlParams } )
.then(response => {
return response ;
})
.catch(function(error) {
console.error ( error )
return error.response;
})
}
// Action !!!
getServerData(url , url_params)
.then( response => {
if ( response.status === 204 ) {
var warningMsg = response.statusText
console.warn ( warningMsg )
return
} else if ( response.status === 404 || response.status === 400) {
var errorMsg = response.statusText // + ": " + response.data.msg // this is my api
console.error( errorMsg )
return ;
} else {
var data = response.data
var dataType = (typeof data)
if ( dataType === 'undefined' ) {
var msg = 'unexpected error occurred while fetching data !!!'
// pass here to the ui change method the msg aka
// showMyMsg ( msg , "error")
} else {
var items = data.dat // obs this is my api aka "dat" attribute - that is whatever happens to be your json key to get the data from
// call here the ui building method
// BuildList ( items )
}
return
}
})
</script>
After 6 hours of fluttering, I realized it was a one-line problem. If you are interfering with the axios life-cycle, you may have forgotten this line:
componentDidMount() {
this.requestInterceptor = axios.interceptors.request.use((request) => {
this.updateApiCallFor(request.url, true);
return request;
});
this.responseInterceptor = axios.interceptors.response.use((response) => {
this.updateApiCallFor(response.config.url, false);
return response; // THIS LINE IS IMPORTANT !
}, (error) => {
this.updateApiCallFor(error.config.url, false);
throw error;
});
async makes a function return a Promise
await makes a function wait for a Promise
code async/await
// https://www.npmjs.com/package/axios
const axios = require('axios')
/* --- */
async function axiosTest() {
let promiseAxios = axios.get( 'https://example.com' )
/* --- */
console.log( await promiseAxios )
}
/* --- */
axiosTest()
replit.com Stackoverflow - Returning data from Axios API
replit.com Stackoverflow - How to return values from async
code async/await with return
// https://www.npmjs.com/package/axios
const axios = require('axios')
/* --- */
async function axiosTest() {
console.log( await promiseAxios() )
}
/* --- */
axiosTest()
/* --- */
// create function for promise axios and return it
function promiseAxios() {
return axios.get( 'https://example.com' )
}
replit.com Stackoverflow - Returning data from Axios API - return
replit.com Stackoverflow - How to return values from async - return
Try this,
function axiosTest() {
axios.get(url)
.then(response => response.data)
.catch(error => error);
}
async function getResponse () {
const response = await axiosTest();
console.log(response);
}
getResponse()
It works, but each function where you want to get the response needs to be an async function or use an additional .then() callback.
function axiosTest() {
axios.get(url)
.then(response => response.data)
.catch(error => error);
}
async function getResponse () {
axiosTest().then(response => {
console.log(response)
});
}
getResponse()
If anyone knows a way to avoid this please do tell.
Also checkout Katsiaryna (Kate) Lupachova's article on Dev.to. I think it will help.
async handleResponse(){
const result = await this.axiosTest();
}
async axiosTest () {
return await axios.get(url)
.then(function (response) {
console.log(response.data);
return response.data;})
.catch(function (error) {
console.log(error);
});
}
You can find check https://flaviocopes.com/axios/#post-requests url and find some relevant information in the GET section of this post.
You can use Async - Await:
async function axiosTest() {
const response = await axios.get(url);
const data = await response.json();
}
I appreciate that there are many questions on this but I can't seem to find a relevant answer.
I am using a Meteor call with a callback to a method on the server that shrinks an URL via bitly, but although this runs on the server, I am getting a undefined response back on the client.
Any ideas here is the code?
Client
Meteor.call('bitlyShrink','http://test.com', function(error, response) {
console.log(error);
console.log(response);
})
Server
Meteor.methods({
bitlyShrink(longurl) {
check (longurl, String);
const BitlyClient = require('bitly'),
bitly = BitlyClient('token');
bitly.shorten( longurl )
.then( function ( response ) {
console.log(response);
return response;
})
.catch( (error ) => {
return error;
});
}
});
That's a common mistake made while using Promises in Meteor methods.
To make Meteor resolve a Promise and return result to a client you should return the Promise at the end of this method:
Meteor.methods({
bitlyShrink(longurl) {
check (longurl, String);
const BitlyClient = require('bitly'),
bitly = BitlyClient('token');
const bitlyPromise = bitly.shorten(longurl);
// do something else, if needed
return bitlyPromise;
}
});
You should not add .catch(), it will be added by Meteor automatically.
Useful article to read: Using Promises and async/await in Meteor.
I'm having a little trouble dealing with some Promises in my app, any clarification would be much appreciated.
I've been building a Phoenix/React app loosely based on this tutorial - https://medium.com/#benhansen/lets-build-a-slack-clone-with-elixir-phoenix-and-react-part-3-frontend-authentication-373e0a713e9e - and I'm trying to restructure my code a bit to make it easier for me to build out other aspects of the app in the future.
Initially, when posting login data to my Phoenix server, the function that I was using looked like this (from Login.jsx):
fetch(`${apiUrl}/sessions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({person: person})
}).then(response => {
this.setState({loadingData: false}, () => {
response.json().then(result => {
if(result.status === "error"){
this.setState({error: {isError: true, message: result.message}}, () => {
return;
})
}
else{
this.login(result) //DO SOME OTHER STUFF WITH THE RESULT
}
})
})
}).catch(error => {
console.error("There was an error: " + error);
});
and this worked just fine.
However, I have since restructured my code so that the fetch functionality has been moved into another file. Here's how it looks now (somewhat similar to the tutorial):
fetch.js
let parseResponse = (response) => {
return response.json().then((json) => {
if (!response.ok){
return Promise.reject(json)
}
return json;
});
}
let fetchFunctions = {
post: (url, data) => {
const body = JSON.stringify(data)
fetch(`${apiUrl}${url}`, {
method: 'POST',
headers: headers(),
body: body
})
.then(parseResponse)
}
}
export default fetchFunctions;
Login.jsx
post('/sessions', {person: person})
.then((result) => {
this.login(result) //HERE'S THAT LOGIN FUNCTION I WANT TO RUN
})
Now when I run this, you may not be surprised to learn that I get the error Uncaught TypeError: Cannot read property 'then' of undefined, and I get it, I think... please correct me if I'm wrong, but the reason that this doesn't work is because fetch() is a Promise, but I have now wrapped it inside of a function that is not a Promise.
If I add console.log(json) before the return statement in parseResponse(), I do see my data and it looks good... but how can I get that data out of the Promise and into my component? It seems to me that I need to defined post() as a Promise as well, but I'm not sure how to structure this.
but the reason that this doesn't work is because fetch() is a Promise, but I have now wrapped it inside of a function that is not a Promise.
Functions are not promises. Functions can return promises. You simply forgot to return the result of fetch, which is a promise, from post:
let fetchFunctions = {
post: (url, data) => {
const body = JSON.stringify(data)
return fetch(`${apiUrl}${url}`, {
// ^^^^^^
method: 'POST',
headers: headers(),
body: body
})
.then(parseResponse)
}
}
Now post returns a promises as well.
If you don't return, the implicit return value will be undefined, hence the error message "Uncaught TypeError: Cannot read property 'then' of undefined"
Simplest repro case for this error:
function foo(){}
foo().then();