How can I get data from axios promise object? - javascript

I want to get variable from axios Promise data but it doesn't assign my variable.
const axios = require('axios');
let url = 'localhost:3000'
let id = ''
let token = 'my-token'
let api = axios.create({
baseURL: url,
withCredentials: false,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
"Access-Control-Allow-Origin": "*"
}
})
const getNotices = function (id, token) {
var arr = []
let result = api
.request({
url: `/notices/${id}/${token}`,
method: "get",
})
.then(res => {
arr = res.data
console.log('in', arr)
})
console.log('out', arr)
return arr
}
getNotices(id, token)
I want to print 'arr' but the result is different 'inside' and 'outside' of the api.
the result of code below is
out []
in [Array(3)]
I don't know why it's different.
I want to use this code for vuejs module but I can't export the data.
edit - tyskr's code like this
const getNotices = function (id, token) {
return api
.request({
url: `/notices/${id}/${token}`,
method: "get",
})
.then(res => {
return res.data
})
}
getNotices(id, token).then(function (arr) {
console.log(arr)
})
but I can't access yet like this
const getNotices = function (id, token) {
return api
.request({
url: `/notices/${id}/${token}`,
method: "get",
})
.then(res => {
return res.data
})
}
var result = []
getNotices(id, token).then(function (arr) {
result = arr
})
I think they have different scopes right?

You need to use async await like below.
const getNotices = async function (id, token) {
var arr = []
let result = await api
.request({
url: `/notices/${id}/${token}`,
method: "get",
})
.then(res => {
arr = res.data
console.log('in', arr)
})
console.log('out', arr) // this line is executing before the response you get from url so we need to use async await
return arr

if you re-arranged the code in the following manner:
const getNotices = function (id, token) {
var arr = []
return api
.request({
url: `/notices/${id}/${token}`,
method: "get",
})
.then(res => {
arr = res.data
})
}
getNotices(id, token).then(function(arr){
console.log(arr); //should solve your issue
})
Then you should be able to get a consistent arr value.
Let me know if that does not work ...

You have to get the first index of the response
const axios = require('axios');
let url = 'localhost:3000'
let id = ''
let token = 'my-token'
let api = axios.create({
baseURL: url,
withCredentials: false,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
"Access-Control-Allow-Origin": "*"
}
})
const getNotices = function(id, token) {
var arr = []
let result = api
.request({
url: `/notices/${id}/${token}`,
method: "get",
})
.then(res => {
arr = res.data[0]
console.log('in', arr)
})
console.log('out', arr)
return arr
}
getNotices(id, token)

Related

Trying to get an id from an array of objects with cypress

I have to find a id from an array of objects with id, emails, birthday, etc
but i end up getting in the way
I thought of getting the index returned from the array, that has the right email/user (i.g: c#c.com),
and then accessing and returning the id, or something like that
How can i do it properly?
Cypress.Commands.add('getId', (user, passwd) => {
// user = c#c.com
let arr = []
cy.getToken(user, passwd).then(token => {
cy.request({
method: 'GET',
url:'/users',
headers:{ Authorization: `Bearer ${token}` }
}).its('body.data.data').then((list) => Cypress._.map(list, 'email')).should('contain', 'c#c.com')
.then(res => arr.push(res))
}).then(() => {
index = cy.log(arr.indexOf("c#c.com"))
return index
})//.its('body.id').then(id => {
//return id
//})
})
but this index return -1, and if i do cy.log(arr) returns the proper array, so i can't test if i can access the body.id by it
My getToken code:
Cypress.Commands.add('getToken', (user, passwd) => {
cy.request({
method: 'POST',
url: '/auth/login',
body: {
email: user,
password: passwd
}
}).its('body.data.token').should('not.be.empty')
.then(token => {
return token
})
} )
You have your results array nested within another array.
See screen grab shows [Array(8)] and item 0 is ['Leon', ...
So either:
Cypress.Commands.add("getId", (user, passwd) => {
let arr = []
cy.getToken(user, passwd)
.then((token) => {
cy.request({
method: "GET",
url: "/users",
headers: { Authorization: `Bearer ${token}` },
})
.its("body.data.data")
.then((list) => Cypress._.map(list, "email"))
.should("contain", "c#c.com")
.then((res) => arr.push(res));
})
.then(() => {
index = arr[0].indexOf("c#c.com")
cy.log(index)
return index;
});
})
or:
Cypress.Commands.add("getId", (user, passwd) => {
cy.getToken(user, passwd)
.then((token) => {
cy.request({
method: "GET",
url: "/users",
headers: { Authorization: `Bearer ${token}` },
})
.its("body.data.data")
.then((list) => Cypress._.map(list, "email"))
.should("contain", "c#c.com")
})
.then(arr => {
index = arr.indexOf("c#c.com")
cy.log(index)
return index;
});
})
Also .then((list) => Cypress._.map(list, "email")) is dubious, the "email" is supposed to be a function.
cy.log() yields null. Try just returning the value instead of the one assigned.
.then(() => {
return arr.indexOf("c#c.com")
});
...

Uncaught (in promise) TypeError: res.map is not a function

I'm trying to fetch a list of departments from an url in a react native application
import React,{ useState,useEffect} from 'react';
import { StyleSheet, LogBox,View,Text } from 'react-native';
export default function App() {
var [department,setDepartment]=useState([])
const token = /* my token here */
const getDepartments=()=>{
const url = /*my api's url here*/
return fetch(url, {
method: 'GET',
headers: { "Authorization": "Bearer" + token ,
'Accept': 'application/json',
'Content-Type':'application/json'
}
})
.then(response => response.json())
.then(data=>console.log(data)) // returns the correct data
.catch(error => console.error(error))
}
const getdepartment = async () => {
await getDepartments().then((res) => //here lays the problem
{res.map((p, key) => {
department.push({
name: p.name,
id: p.id,
});
});
});
};
useEffect(() => {
getdepartment();
}, []);
return (
<View>
<Text>
{department[0]}
</Text>
</View>
)
}
here res in the getdepartment() function is undefined despite the getDepartments() function returning correct data from the url
You are not returning a value from getDepartments, just a simple console.log.
You can convert the function in async/await:
const getDepartments = async () => {
const url = /*my api's url here*/
try {
const response = await fetch(url, {
method: 'GET',
headers: { "Authorization": "Bearer" + token ,
'Accept': 'application/json',
'Content-Type':'application/json'
}
})
return await response.json();
} catch(e){
// error
}
}
or return a value from your function:
const getDepartments=()=>{
const url = /*my api's url here*/
return fetch(url, {
method: 'GET',
headers: { "Authorization": "Bearer" + token ,
'Accept': 'application/json',
'Content-Type':'application/json'
}
})
.then(response => response.json())
.catch(error => console.error(error))
}
If you are returning the result of the fetch then just return the result obtained from it, the issue is along with fetch, the response is also handled and the complete thing post to that is being returned which is not the result so you just need to skip this line .then(data=>console.log(data))
const getDepartments=()=>{
const url = /*my api's url here*/
return fetch(url, {
method: 'GET',
headers: { "Authorization": "Bearer" + token ,
'Accept': 'application/json',
'Content-Type':'application/json'
}
}).then(response => response.json()).catch(error =>
console.error(error))
}
// Here after fetching the result you can map the data
const getdepartment = async () => {
await getDepartments().then((res) =>
{res.map((p, key) => {
department.push({
name: p.name,
id: p.id,
});
});
});
};

Fetch inside map in react

I'm trying to fetch each campaign stats by its campaignId. campaignId is pulled from first api call and then while iterating i'm passing that id to next api call for each campaign stats. First api call gives the right result but while iterating and fetching it from second api call it throws and error of
Unhandled Rejection (TypeError): ids.map is not a function
export const loadStats = async () => {
const ids = await (await fetch('https://api.truepush.com/api/v1/listCampaign/1', {
method: "GET",
headers: {
Authorization: `${TOKEN}`,
"Content-Type": "application/json"
}
})).json()
const data = Promise.all(
ids.map(async (i) => await (await fetch(`https://api.truepush.com/api/v1/campaignStats/${i.data.campaignId}`, {
method: "GET",
headers: {
Authorization:`${TOKEN}`,
"Content-Type": "application/json"
}
})).json())
)
return data
};
I'm expecting all such stats while iterating:
https://i.stack.imgur.com/8kjwy.png
https://i.stack.imgur.com/VJni7.png (result of listCampaign/1)
Try this:
export const loadStats = async () => {
const ids = await (await fetch('https://api.truepush.com/api/v1/listCampaign/1', {
method: "GET",
headers: {
Authorization: `${TOKEN}`,
"Content-Type": "application/json"
}
})).json()
const data = Promise.all(
ids.data.map(async (i) => await (await fetch(`https://api.truepush.com/api/v1/campaignStats/${i.campaignId}`, {
method: "GET",
headers: {
Authorization:`${TOKEN}`,
"Content-Type": "application/json"
}
})).json())
)
return data
};

Why i got the output as "\"userName\"" and not like that "userName"?

Why i got output "\"userName\"" and not as "userName" ?
in my example i try to do an get api that attach to it some data and that data comes from the async-storage.
when i console the output so its shows the data like that :
"\"userName\""
but it should output "userName" .
what is the way to fix that issue ?
so what is wrong in my way ?
const getSaveUserTokenData = async (data) => {
const url =
'https://URL/userName,userToken,PlatformType,DeviceID?' +
'userName=' +
data.userName +
'&userToken=' +
data.googlToken +
'&PlatformType=' +
data.platformId +
'&DeviceID=' +
data.deviceId;
await fetch(
url,
{
method: 'GET',
headers: {
Authorization: data.azureToken,
},
}
)
.then((response) => response.json())
.then((data) => {
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
});
};
You can write this way as well:
fetchFunction = async () => {
let data = {
userName: 'jon',
userToken: 'bee22',
PlatformType: 'os-ios',
DeviceID: '222222'
}
const url = `https://yoururl.com/?userName=${encodeURIComponent(data.userName)}&userToken=${encodeURIComponent(data.userToken)}&PlatformType=${encodeURIComponent(data.PlatformType)}&DeviceID=${encodeURIComponent(data.DeviceID)}`;
const response = await fetch(url, {
method: 'GET',
headers: {
'Authorization': 'Basic ' + btoa('username:password'),
'Accept': 'application/json',
'Content-Type': 'application/json',
},
});
const json = await response.json();
console.log(json);
}
If your variable names are the one you want in your url, try this:
const getData = async () => {
let userName = 'jon';
let userToken = 'bee22';
let PlatformType = 'os-ios';
let DeviceID = '222222';
const queryString = Object.entries({
userName,
userToken,
PlatformType,
DeviceID,
})
.map(([key, value]) => `${key}=${encodeURIComponent(value)}`)
.join('&');
const response = await fetch(
'https://url...?' + queryString
);
};
};
Note: user token should not be in the url but usually in the headers of your request, like so:
fetch(someUrl, {
headers: {
Authorization: userToken
}
});
fetch(`https://yoururl.com/${userName}`,
{ method: 'GET',
headers: myHeaders,
mode: 'cors',
cache: 'default'
})
.then(function(response) {
//your code here
});
A more generic solution would be something like this:
async function get(route, ...params) {
const url = `${route}${params.map(p => `/${p}`)}`;
const response = await fetch(url, { method: "GET", headers });
if (!response.ok)
throw new Error(`Http error status: ${response.status}`);
return response.json();
}
by using ...params you can pass a generic amount of parameters that will then be combined with:
const url = `${route}${params.map(p => `/${p}`)}`;
In your case you would call the method like this:
const result = await get("https://url..", "jon", "bee22", "os-ios", "222222");

Use Async with .then promise

Hello after setup a simple async function with promise return i'd like to use then promise instead of try!
But is returning
await is a reserved word
for the second await in the function.
i've tried to place async return promise the data! but did not worked either
async infiniteNotification(page = 1) {
let page = this.state.page;
console.log("^^^^^", page);
let auth_token = await AsyncStorage.getItem(AUTH_TOKEN);
fetch(`/notifications?page=${page}`, {
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Access: auth_token
},
params: { page }
})
.then(data => data.json())
.then(data => {
var allData = this.state.notifications.concat(data.notifications);
this.setState({
notifications: allData,
page: this.state.page + 1,
});
let auth_token = await AsyncStorage.getItem(AUTH_TOKEN);
fetch("/notifications/mark_as_read", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Access: auth_token
},
body: JSON.stringify({
notification: {
read: true
}
})
}).then(response => {
this.props.changeNotifications();
});
})
.catch(err => {
console.log(err);
});
}
> await is a reserved word (100:25)
let auth_token = await AsyncStorage.getItem(AUTH_TOKEN);
^
fetch("/notifications/mark_as_read", {
You should refactor how you make your requests. I would have a common function to handle setting up the request and everything.
const makeRequest = async (url, options, auth_token) => {
try {
// Default options and request method
if (!options) options = {}
options.method = options.method || 'GET'
// always pass a body through, handle the payload here
if (options.body && (options.method === 'POST' || options.method === 'PUT')) {
options.body = JSON.stringify(options.body)
} else if (options.body) {
url = appendQueryString(url, options.body)
delete options.body
}
// setup headers
if (!options.headers) options.headers = {}
const headers = new Headers()
for(const key of Object.keys(options.headers)) {
headers.append(key, (options.headers as any)[key])
}
if (auth_token) {
headers.append('Access', auth_token)
}
headers.append('Accept', 'application/json')
headers.append('Content-Type', 'application/json')
options.headers = headers
const response = await fetch(url, options as any)
const json = await response.json()
if (!response.ok) {
throw json
}
return json
} catch (e) {
console.error(e)
throw e
}
}
appendQueryString is a little helper util to do the get qs params in the url
const appendQueryString = (urlPath, params) => {
const searchParams = new URLSearchParams()
for (const key of Object.keys(params)) {
searchParams.append(key, params[key])
}
return `${urlPath}?${searchParams.toString()}`
}
Now, to get to how you update your code, you'll notice things become less verbose and more extensive.
async infiniteNotification(page = 1) {
try {
let auth_token = await AsyncStorage.getItem(AUTH_TOKEN);
const data = await makeRequest(
`/notifications`,
{ body: { page } },
auth_token
)
var allData = this.state.notifications.concat(data.notifications);
this.setState({
notifications: allData,
page: this.state.page + 1,
});
const markedAsReadResponse = makeRequest(
"/notifications/mark_as_read",
{
method: "POST",
body: {
notification: { read: true }
},
auth_token
)
this.props.changeNotifications();
} catch (e) {
// TODO handle your errors
}
}

Categories