i got error " Cannot read property 'then' of undefined" - javascript

Im getting this error:
TypeError: Cannot read property 'then' of undefined in controller
[controller]
fetchGameData() {
DataModel.getList().then(data => {
console.log(data);
})
}
[DataModel]
export default {
getList() {
fetch('URL')
.then((res) => {
return Promise.resolve(res.json());
})
.catch((err) => {
console.log("Fetch Error!!!", err);
})
}
}

The error is already clear actually. Your function getList() does not return anything which is going to be undefined in JavaScript. You should return "something" at the end of your function. If you want to use .then on the return value of your function, you probably want to return a "Promise"
fetch function will return a Promise anyway. So can simply return that. You can find more info about fetch here https://javascript.info/fetch
So a neater alternative would be
export default {
getList() {
return fetch('URL')
.then((res) => {
return Promise.resolve(res.json());
})
.catch((err) => {
console.log("Fetch Error!!!", err);
})
}
}

You need to return a promise to do .then
export default {
getList() {
return new Promise((resolve, reject) => {
fetch("URL")
.then((res) => {
resolve(res.json());
})
.catch((err) => {
console.log("Fetch Error!!!", err);
});
});
},
};

[Service]
async function getList() {
const result = await fetch('URL')
.then((res) => {
return Promise.resolve(res.json());
})
.catch((err) => {
console.log("Fetch Error!!!", err);
})
return result.json();
}
[controller]
fetchGameData() {
DataModel.getList().then(data => {
console.log(data);
})
}

You are getting that error because the DataModel.getList() doesn't return a Promise so you can have access to Promise then chain. All you have to do is to add a return keywork in the getList before the fetch function so the getList method can return a resolve Promise instead of undefined
export default {
getList() {
return fetch('URL')
.then((res) => {
return Promise.resolve(res.json());
})
.catch((err) => {
console.log("Fetch Error!!!", err);
});
}
}

You should return the promise inside your getList() function.
otherwise a function with no return will return undefined.
And this you will have the error "...cant read then of undefined"
your code should be :
export default {
getList() {
return fetch('URL')
.then((res) => {
return Promise.resolve(res.json());
})
.catch((err) => {
console.log("Fetch Error!!!", err);
})
}
}

Related

Function returning undefined

I have a function that calls an API and returns some data:
async function getDataAxios(){
await axios.get("http://localhost:8080/cards/1").then(response => {
console.log("RESP: ", response.data[0])
return response
})
.catch(err => {
console.log("Error: ", err)
return err
})
}
When I log response.data[0] inside getDataAxios() the expected data is present.
But when I try and return the data to my calling function and log the return data it logs undefined:
getDataAxios().then(r => console.log(r))
I have also tried the following:
const resp = getDataAxios().then(resp => console.log("Data 2: ", resp)).catch(
err => {
console.log("An error has occurred: ", err)
return err;
}
)
console.log(resp)
Full code:
function App() {
getDataAxios().then(r => console.log(r))
}
async function getDataAxios(){
await axios.get("http://localhost:8080/cards/1").then(response => {
console.log("RESP: ", response.data[0])
return response
})
.catch(err => {
console.log("Error: ", err)
return err
})
}
export default App;
Just adding here some more details, since the comment was not very detailed.
You have
async function getDataAxios(){
await axios.get(...).then(...).catch(...);
}
and
function App() {
getDataAxios().then(r => console.log(r))
}
The getDataAxios method does not return anything. The then inside it does return a value, but that is not returned from the actual getDataAxios function.
Nothing wrong with that on its own, if the then code is all you wanted to perform.
But you then call it in the App and use then on it, getDataAxios().then(r => console.log(r)). The r here will contain whatever was returned from the getDataAxios which is nothing, so the r will be undefined.
Adding the return to the getDataAxios will return the promise. And since the return value type of axios is a promise you do not have to specify async, nor await for it.
So you can use
function getDataAxios(){
return axios.get(...).then(...).catch(...);
}
and now you can use it as you already do, as
function App() {
getDataAxios().then(r => console.log(r))
}
Turn the response into a constant and than store data in it and than return it. Do this instead.
async function getDataAxios(){
await axios.get("http://localhost:8080/cards/1").then(response => {
console.log("RESP: ", response.data[0])
const response = response.data[0]
return response
})
.catch(err => {
console.log("Error: ", err)
return err
})
}
Or you can do this
async function getDataAxios(){
await axios.get("http://localhost:8080/cards/1").then(response => {
console.log("RESP: ", response.data[0])
return response.data[0]
})
.catch(err => {
console.log("Error: ", err)
return err
})
}

Cannot read property 'then' of undefined for axios wrapper

I have a bit of a similar issue like this but I can't seem to get it right. I know I have to return a promise and I think I do, although it's still not accepted. Here is my wrapper function for axios calls:
export const callGraph = (url, token) => {
return axios.get(url, {headers: { Authorization: `Bearer ${token}` }})
}
This is the function that invokes callGraph that in turn should return a Promise:
export const getGraphProfile = () => {
if (auth.getAccount()) {
auth.getToken(loginRequest)
.then(response => {
return callGraph(graphConfig.graphMeUrl, response.accessToken)
})
.catch(error => { console.log(error) })
}
}
As you can see I explicitly request return callGraph so I can use it like this:
getGraphProfile()
.then(response => { console.log('givenName ', response.data.givenName) })
.catch(error => console.log(error))
For one reason or another I'm still missing something. Thank you for your help.
You should return the axios promise
export const getGraphProfile = () => {
if (auth.getAccount()) {
return auth.getToken(loginRequest)
.then(response => {
return callGraph(graphConfig.graphMeUrl, response.accessToken)
})
.catch(error => { console.log(error) })
}
}

While using .fetch, can I chain together existing .fetch functions into a larger synchronous query?

I know how to chain all of this together into one function. I am confused on how I'd incorporate the following function's return value into another?
function queryPlayers() {
fetch("foo", apiParams)
.then(res => {
if(res.ok){ return res.json() }
else { return fetch("backup_bar", apiParams)
.then(res => { return res.json() }
)}
})
.then(playerData => { return playerData })
.catch(err => console.log(err))
}
All I want to do is take playerData, or the JSON I receive and throw it into another function as an argument once the promise resolves. I'm quite new to arrow functions and promises and I feel I just am missing something.
function getExtraData(playerData){
fetch("some_foo" + playerData)
.then(newData => doStuff())
}
For reference, here is what I ended up doing as a super basic answer to the question:
function queryPlayers() {
console.log("Querying players...");
return fetch("https://api-v2.royaleapi.com/top/players", apiParams)
.then(res => {
if(res.ok){ return res.json() }
else { return fetch("http://127.0.0.1:8000/js/players.json", apiParams)
.then(res => res.json()
)}
})
.then(playerData => {
return playerData;
})
.catch(err => console.log(err))
}
function queryData(){
queryPlayers()
.then(data => console.log(data))
}
$(function(){
queryData();
});

My Vue.js code about Axios and function is not working

I want to execute function2 after axios. I got no catch error. but still Function2 is not executed.
The code i want but not working :
add: function () {
axios.post('/add', this.person)
.then(response => {
if (response.data.etat) {
this.person = {};
this.function2();
}
})
.catch(error => {
console.log('errors: ', error)
})},
This is working, but i would like to execute function2 only if axios pass.
add: function () {
axios.post('/add', this.person)
.then(response => {
if (response.data.etat) {
this.person = {};
}
})
.catch(error => {
console.log('errors: ', error)
})
this.function2();
},
Any help ? thank you !
You can chain .then() blocks:
add: function () {
axios.post('/add', this.person)
.then(response => {
if (response.data.etat) {
this.person = {};
}
})
.then(() => {
this.function2();
})
.catch(error => {
console.log('errors: ', error)
})
}
this.function2 will be called only if your axios.post is successful and if the first .then() doesn't throw any error. In another case - your .catch() will catch the error.
Here you can see how it works on live:
https://codepen.io/anon/pen/gZQyym?editors=1111
Since you're using axios to post data, and you want to do call that method after the operation is done successfully so you should check the response status like :
add: function () {
axios.post('/add', this.person)
.then(response => {
if (response.status==200) {
this.person = {};
this.function2();
}
})
.catch(error => {
console.log('errors: ', error)
})},

Why is this promise not resolving back to the caller?

I have a Vue-App which runs with Vuex and Axios. In this app I have vuex-store which handles API-calls, but a problem is that when I call the store-actions I cant chain the response in the caller.Any ideas what Im doing wrong?
Calling code:
import { FETCH_PRODUCTS, ADD_PRODUCT } from './actions.type'
methods: {
sendNewProduct () {
this.$store
.dispatch(ADD_PRODUCT, this.newProductForm)
.then(() => {
console.log('This never gets called')
})
}
}
Vuex-store:
const actions = {
[ADD_PRODUCT] (context, credentials) {
return new Promise((resolve) => {
ApiService
.post('/Products/', {
Name: credentials.Name,
Description: credentials.Description,
Price: credentials.Price
})
.then(({ data }) => {
this.$store
.dispatch(FETCH_PRODUCTS)
resolve(data)
})
.catch(({ response }) => {
console.log(response)
context.commit(SET_ERROR, 'Error adding product')
})
})
}
}
const actions = {
[ADD_PRODUCT](context, credentials) {
return ApiService.post("/Products/", {
Name: credentials.Name,
Description: credentials.Description,
Price: credentials.Price
})
.then(({ data }) => {
this.$store.dispatch(FETCH_PRODUCTS);
return data;
})
.catch(({ response }) => {
console.log(response);
context.commit(SET_ERROR, "Error adding product");
throw new Error("Error adding product");
});
}
};
I've removed the new Promise(...) because axios already creates a promise.
If added a return data in the then callback and a throw in the catch callback to let the calling api receive the data/error.
Note that the promise resolves before the FETCH_PRODUCTS completes, to make sure that action is also completed, you'd write:
.then(({ data }) => {
return this.$store.dispatch(FETCH_PRODUCTS)
.then(() => data);
})

Categories