I have a few problem while integrating api from OpenWeather.
I can successfully log the response data value from the api. But when i call from another component with .then(), throw me the error.
The following is my api.js call with axios
function getFiveDayForcast(cityName) {
axios.get(`http://api.openweathermap.org/data/2.5/forecast/daily?q=${cityName}&type=accurate&APPID=${apiKey}&cnt=5`)
.then(function(response){
// console.log("response" , response.data);
return response.data;
})}
module.exports= {getFiveDayForecast:getFiveDayForecast}
This is when i call back from my Component
componentDidMount(){
let city = queryString.parse(this.props.location.search).city;
this.makeRequest(city);
}
makeRequest =(city) => {
//set loading false
this.setState(()=> ({loading:false}));
api.getFiveDayForecast(city).then((response) => {
console.log(response)
})
}
And it throw
TypeError: Cannot read property 'then' of undefined
Would be nice if someone can explain in details about it. I am also reading documentation as well. Thanks in advance.
Posting my answer here so more people can see.
Referring to Returning an Axios Promise from function
The complaint is that a function needs to return something in order for the then chain to know what to do. The function preceding the then chain is not returning anything, so the function inside then then chain doesn't know what to do.
Axios takes care of this for the get action, but you aren't directly chaining the get method to then. Instead, you are chaining a method you created, getFiveDayForcast.
You should change getFiveDayForcast(cityName) (btw 'Forecast' is the right spelling) to
function getFiveDayForcast(cityName) {
const request = axios.get(`http://api.openweathermap.org/data/2.5/forecast/daily?q=${cityName}&type=accurate&APPID=${apiKey}&cnt=5`)
.then(function(response){
// console.log("response" , response.data);
return response.data;
})
return request;
}
You need to return the Promise from your Function getFiveDayForcast.
function getFiveDayForcast(cityName) {
return axios.get(`http://api.openweathermap.org/data/2.5/forecast/daily?q=${cityName}&type=accurate&APPID=${apiKey}&cnt=5`)
.then(function(response){
// console.log("response" , response.data);
return response.data;
})
}
I am new to MEAN environment and not an expert in using promises. I am confused how to achieve this behaviour using promise.
my router method makes call to service method which has promise chained to qyery DB and returns results. I want to send back those results to router so I can send to front end. Thats there problem lies and I get undefined.
Router.js:
myrouter('/api/getDatafromDB',(req,res){
results =getSQLResults();
res.send(results); //want to achieve that.
}
SQLServiceFile.js :
//Db connection code defined in separate js file - dbConfig.js and
//imported in connection object
getSQLResults=function(){
connection.connect().then( //promise1
function(recordset){
request.query('select * from xyz') //promise 2
.then(
//recordset fetched fine here and want to pass to router.
rec= recordset['recordset']; //basically want to pass back rec.
console.log(rec);
connection.close();
).catch(function(err){
//error handling}
connection.close();)
}
).catch(//error handling code);
}
I tried different variations but did not work. Now I think somewhere I read that I need to pass back callback again in promise or something like that. I don't know. But I think If I change my code to use callbacks and not promise, it would work Or If I put back sql query code in router.
I want to keep code structured like this so please suggest right method.
Your code is syntactically wrong. Maybe the below piece of code will help you, it's the right way to use promises and async programming. The pattern used below is known as .then chaining. We can chain multiple .then to achieve a synchronous pattern in js.
.then and .catch only accept a function as an argument.
myrouter('/api/getDatafromDB', (req,res) => {
getSQLResults()
.then( result => res.send(results) )
.catch( err => ErrorHandler(err) )
}
SQLServiceFile.js :
//Db connection code defined in separate js file - dbConfig.js and
//imported in connection object
function getSQLResults() {
return connection.connect()
.then( function() {
return request.query('select * from xyz')
})
.then( function(recordset) {
connection.close();
return recordset['recordset'];
})
.catch( function(err) {
connection.close();
throw err; // it can be done so that you can handle the errors in myRouter
});
}
fetch() is a great improvement over the classic XMLhttpRequest() However I was wondering if I add window.addEventListener('unhandledrejection', event => ยทยทยท); to my index.android.js and index.ios.js could I theoretically remove all of my .catch() from my promise chains and make a pseudo global promise rejection handler? I am building a react native app that relies heavily on api calls, many of which are authenticated with user tokens. When a user logs in a token is stored in asynchronous storage, but each token will expire after a certain amount of time. if a user opens the app and unwittingly attempts to make a call that requires authentication with an expired token I would like the user to be routed to the login page regardless of what call was made, or what component the call is in. I currently have each individual promise chain handling unauthenticated calls on their own. Is there a better way to do it?
You could make a custom abstraction on top of fetch, which will provide a way of communicating with API and also have some business logic, which for you case is to request an auth token or make a redirect. Then you use this abstraction in the rest of the code to make API calls. Here is a small example to demonstrate the idea:
export default function request(url, options = {}) {
const req = fetch(url)
.then((response) => {
// Global response handler
// ...
// Hand response down the promise chain
return response;
})
.catch((err) => {
// Global error handler
// Check error status and (make redirect/request auth token)
// Throw error down the promise chain if needed
throw err;
});
// Returns a promise
return req;
}
Then you use it in your code like fetch(), but instead you'll be able to modify and extend it for you needs any time.
request('http://example.com/api/post/1')
.then((response) => {
// "response" has whatever you returned from global handler
})
.catch((err) => {
// "err" is whatever you've thrown from global handler
});
I have a requirement wherein I need to load the data through an ajax call to server and then pass on the data to reducer to render my page through props.
But I see the data in the ajax call is being shown as undefined.
function getInitData(url) {
axios({url: url, timeout: 20000, method: 'get', responseType: 'json'})
.then(function(response) {
console.log(response.data.results)//--DATA DISPLAYED
return response.data.results
})
.catch(function(response) {
console.error(response.data);
})
}
let formActions = {
loadInitJSONSchema: function(formSchema) {
let dataLoaded = getInitData('/startInterview')
console.log(dataLoaded);//--DATA DISPLAYED as UNDEFINED
return {type: 'LOAD_INIT_JSON_SCHEMA', formSchema: dataLoaded}
}
}
I dont know why my data displayed as undefined in my actual method may be it is because of the asynchrnous call?? If so how do I load my data in actions??
Please find the complete code at the URL
It's promises all the way down.
A jQuery example: jQuery('body') does not return the body element. It returns a jQuery collection. jQuery('body').css('background', 'red'); also returns a jQuery collection. It's collections all the way down.
axios.get().then(function(response) { return response; }) does not return response. It returns a promise.
First, change this, to return the promise:
function getInitData(url) {
return axios...
Then change your function:
loadInitJSONSchema: function(formSchema) {
return getInitData('/startInterview').then(function(data) {
return {type: 'LOAD_INIT_JSON_SCHEMA', formSchema: data}
})
Then anyone who uses loadInitJSONSchema gets the promise and gets the value in a .then().
loadInitJSONSchema(schema).then(function(result) { ... do something with result })
It's promises all the way down.
This flow is asynchronous. With var something = axios.get().then(function(response) { return response; }) the code is evaluated in place and the program keeps going. The .then() callback happens at a later time, long after the current function has finished executing.
How is result passed from the $http object to the unnamed function that is executed on success?
$http
.success(function (result) {
...
})
I know that the result is passed via any variable name that i put into the function. It is typically called result. But how is this done? It seems like wizardry to me.
I would expect to have to write something like:
$http
.success(function (result=$http.result) {
...
})
You have to study how both Javascript Function Paramters and Promises work.
The code that you pasted comes, I Think, from some AngularJS Application.
If my assumption is correct, $http is a service and doesn't have anyone success method.
The success method is present on $http methods:
//get, post, ecc...
$http.get(...).success()
By the way:
Javascript doesn't provide any way to match parameters, their order is always the order provided by the callee and the names that you use is just for you (Don't confuse with the IOC that the DependencyInjection in AngularJS does). EXAMPLE 1
function loggerCase1(log1, log2, log3, log4) {
console.log('loggerCase1 => param-1:', log1);
console.log('loggerCase1 => param-2:', log2);
console.log('loggerCase1 => param-3:', log3);
console.log('loggerCase1 => param-4:', log4);
console.log('---------------------');
};
function loggerCase2(log4, log2, log1, log3) {
console.log('loggerCase2 => param-1:', log4);
console.log('loggerCase2 => param-2:', log2);
console.log('loggerCase2 => param-3:', log1);
console.log('loggerCase2 => param-4:', log3);
console.log('---------------------');
};
function loggerCaseN() {
for(var i = 0; i < arguments.length; i++) {
console.log('loggerCaseN => param-' + (i + 1) + ': ', arguments[i]);
}
console.log('---------------------');
};
var logs = ['log1', 'log2', 'log3', 'log4'];
loggerCase1.apply(this, logs);
loggerCase2.apply(this, logs);
loggerCaseN.apply(this, logs);
If it's all clear about function parameters behaviour in javascript... you will know that isn't possibile to say give me the first as the second or something like that, also, the example that you pasted seems similar to default parameters (implemented in ES6, aka Javascript Harmony).
Let's go to the point 2:
In a simple promise chain (find on google or see the link above) you can pass a result to the next callback using return. EXAMPLE2
angular
.module('promisechainging', [])
.run(function($q) {
$q
.when('Hello World')
.then(function(greetings) {
console.log('ring 1', greetings);
return greetings;
})
.then(function(salut) {
console.log('ring 2', salut);
return salut;
})
.then(function(ciao) {
console.log('ring 3', ciao);
return { message: ciao };
})
.then(function(result) {
console.log('ring 4', result.message);
return result;
})
.catch(function(error) {
console.log('THIS LOG NEVER HAPPENS BECAUSE THERE AREN\'T REJECTED PROMISES');
return $q.reject(error);
})
.finally(function() {
console.log('We Are At The END');
})
;
})
;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="promisechainging"></div>
Basically is not important how parameters are named!
Angular is using the promise mechanism which basically returns an object that let you know when the result is available or an error has been thrown.
When the ajax call returns, angular is calling the promise and providing the result as a parameter.
It's just like calling a regular function.
$http allows you to perform async network operations and returns a promise object (you can read more about promises in Angular here).
The success and error methods were used to declare callbacks to what happens when the promise is resolved (when the request was successfully completed) or rejected (when there was an error at processing the request). I used the past tense since they are now deprecated and the desired way to handle these is using the then method of the promise object.
// Simple GET request example:
$http({
method: 'GET',
url: '/someUrl'
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
Basically, the syntax is pretty much the same - the successCallbackFunction has the same signature as the method you were passing in the success method of your example.
But this is only the method signature. Your callback function parameters can be called however you want (result, data etc). All you have to keep in mind is that the first parameter in your callback function is going to be the data returned by your request.
$http
.success(function (result) {
...
})
$http will return a Promise Object which is nothing but a Javascript Object with success and different other functions.
So the statement immediately becomes like below as $http is evaluated,
(Promise Object)
.success(function (result) {
...
})
The success function of promise will save this anonymous function to be called once the promise is resolved. We can manually resolve promises, but I guess http will do this for you here.
Once http request(AJAX) is successful angular will tell this Promise object to run this success function by resolving the Promise, somewhat like:
suceess: function(responseData){ //success of AJAX
resolve(responseData); //this will pass the result to promise
}
Once resolve is called promise object has the result with it, it will then call the success function you passed initially with this value of result.
PS: This is a rough idea, I ave to look into Angular source to see their actual implementation.
Javascript functions are also class objects.
When $http completes it will call either the success or fail function - they are objects so they can be passed around. When it does, it will provide the parameters.