fetch request returning promise [duplicate] - javascript

This question already has answers here:
How to return many Promises and wait for them all before doing other stuff
(6 answers)
Closed 4 months ago.
i created a function named getCartItems which calls getSingleItems passing id as argument. if i log the json result in getSingleItem it is showing object of the product correctly but when i try to access the function call value i get a promise how to resolve it?
const getSingleItem = async (id)=>{
const response = await fetch("http://localhost:4000/products/"+id, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
})
const json = await response.json();
return json;
}
const getCartItems = () => {
let currArr = JSON.parse(localStorage.getItem('cart'));
let newArr = currArr.map( async (el)=>await getSingleItem(el.id))
console.log(newArr);
setCartItems(newArr);
}
useEffect(()=>{
getCartItems();
}, [])
if try to use for loop instead of map it shows promise pending and throws connection error.

You need to resolve the promises from the map method with Promise.all and await for it before setting the cartItems state.
const getSingleItem = async (id)=>{
const response = await fetch("http://localhost:4000/products/"+id, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
})
const json = await response.json();
return json;
}
const getCartItems = async () => {
let currArr = JSON.parse(localStorage.getItem('cart'));
let newArr = await Promise.all(currArr.map( async (el)=>await getSingleItem(el.id)))
console.log(newArr);
setCartItems(newArr);
}
useEffect(()=>{
getCartItems();
}, [])

Related

How to collect result from promise call in Javascript? [duplicate]

This question already has answers here:
How to return value from an asynchronous callback function? [duplicate]
(3 answers)
Closed 6 months ago.
function foo() {
let url = `https://foobar.com`
fetch(url, {
method: 'POST',
headers: headers
}).then(response => {
return response.json();
}).then(data => {
return data['jobs'];
}).then(jobs => {
let successful = [];
jobs.forEach(job => {
let jobUrl = job['url'];
fetch(jobUrl, {
headers: headers
}).then(response => {
return response.json();
}).then(data => {
let job_status = data['status'];
let job_timeStamp = data['timestamp'];
if (job_status === 'SUCCESS') {
console.log(job_status, job_timeStamp);
successful.push({jobUrl:jobUrl, timeStamp:job_timeStamp});
}
})
});
console.log(successful);
})
}
foo()
When I am running the above code, successful array is not getting populated. How can I populate the successful array? I should be able to sort that array later based on timestamp.
The issue with your code is that fetch is asynchronous, so none of the fetches will have run yet when you console.log(successful)
Here's two alternatives, using async / await since that will simplify the code immensely - I've also used a liberal amount of destructuring sugar
If all the jobUrl fetches can be done in parallel - use this
async function foo() {
// function to get one jobUrl data
// called by map later on
const getJob = async ({url:jobUrl}) => {
const response = await fetch(jobUrl, {headers});
const {status, timestamp: timeStamp} = await response.json();
if (status === 'SUCCESS') {
return {jobUrl, timeStamp};
}
};
let url = `https://foobar.com`;
const response = await fetch(url, {method: 'POST', headers});
const {jobs} = await response.json();
const unfiltered = await Promise.all(jobs.map(getJob));
// this "unfiltered" array will have `undefined` items for when status !== SUCCESS
// so filter them out
const successful = unfiltered.filter(v => v);
// here you have successful populated and can use it
}
If the jobUrl fetches have to be done one by one - use this
async function foo() {
let url = `https://foobar.com`;
const response = await fetch(url, {method: 'POST', headers});
const {jobs} = await response.json();
const successful = [];
for ({url:jobUrl} of jobs) {
const response = await fetch(jobUrl, {headers});
const {status, timestamp: timeStamp} = await response.json();
if (status === 'SUCCESS') {
successful.push({jobUrl, timeStamp});
}
};
// here you have successful populated and can use it
}

Promise { <pending> } - for last async function

I have two main functions. The first one gets the SOAP data from an API. The second one parses it to json and then formats it into the object I need to store. I have been logging and seeing the return values, and as of so far until now, it's been fine. However, I am calling exports.createReturnLabelfrom my test file and all I can see is Promise { <pending> } . I am returning a value at the last function. Does this code look weird to your? How can I clean it up?
const soapRequest = require('easy-soap-request');
const xmlParser = require('xml2json')
exports.createReturnLabel = async () => {
const xml = hidden
const url = 'https://ws.paketomat.at/service-1.0.4.php';
const sampleHeaders = {
'Content-Type': 'text/xml;charset=UTF-8',
};
const auth = async () => {
const {
response
} = await soapRequest({
url: url,
headers: sampleHeaders,
xml: xml,
timeout: 2000
});
const {
body,
statusCode
} = response;
return body
}
const fetchLabel = async () => {
const soapData = await auth();
try {
const json = xmlParser.toJson(soapData)
const labelData = JSON.parse(json)["SOAP-ENV:Envelope"]["SOAP-ENV:Body"]["ns1:getLabelResponse"]
return {
courier: 'dpd',
tracking_number: labelData["return"]["paknr"],
barCode: labelData["return"]["barcodecontent"],
printLabel: labelData["return"]["label"],
_ref: null
}
} catch (e) {
return (e)
}
}
return fetchLabel()
}
calling from my test file return console.log(file.createReturnLabel())
There's an async function call inside your code.
Should be: return await fetchLabel(), so that it awaits for completion before going on its merry way.

How to wait for JavaScript function to complete in react? [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 2 years ago.
I am trying to fetch data from an endpoint in react but don't know exactly how can I wait for the called function to return and then pass the cursor to next line.
FetchData.js
// ...
componentDidMount () {
const url = 'http...';
const options = {
headers: {'Content-Type': 'application/json'},
method: 'GET'
}
const data = fetchDataFromUrl(url, options);
this.setState({ item: data },
() => this.updateItem())
}
console.log(this.state.item)
// ...
fetchData.js
export const fetchDataFromUrl = (url, options) => {
const repsonse = fetch(url, options)
.then(res => res.json())
.then(data => {
return data
})
}
This does return the data but in console.log() I get undefined, after sometime (ie in some other function) I am able to see the data contents. How can I wait for the fetchDataFromUrl function to fetch the data before the state gets updated. I used
const data = async() => fetchDataFromUrl(url, options); but it does not help.
You can simply use, async and await for your requirement
componentDidMount () {
this.getData()
}
getData= async()=>{
const url = 'http...';
const options = {
headers: {'Content-Type': 'application/json'},
method: 'GET'
}
const data = await fetchDataFromUrl(url, options);
this.setState({ item: data },
() => this.updateItem())
}
user fetch function should also be async function.
export const fetchDataFromUrl = async(url, options) => {
const repsonse = await fetch(url, options);
return repsonse; //Modify you response
}

issue with promise Node.js

I have been trying to figure this out for quite some time and it's too confusing so i thought i'd ask.
var listenKey = "";
const createListenKey = async () => {
await axios({
url: "/api/v3/userDataStream",
method: "POST",
baseURL: "https://api.binance.com",
headers: {
"X-MBX-APIKEY":
"H48w9CLuTtTi955qWjcjjEKhh0Ogb3jnnluYucXXXXXXXXXXXXXXXX",
},
}).then((response) => {
var key = response.data.listenKey;
console.log(key, "created");
return key;
});
};
listenKey = createListenKey();
listenKey.then((key) => {
console.log(key);
});
the console.log in the last but one line is printing undefined. Why is that?
Thanks in advance!
You did not return anything from the async function createListenKey
const asynF = async ()=>{
Promise.resolve(1).then(res=>{
//Simulating response from axios call
console.log(res)
})
// you are not returning anyting from this function equivalent of => return ;
}
asynF().then(res=>{
//this would log undefined
console.log(res)
})
As you know async function returns a promise you have two options make the outer wrapper a async function as well and just use await like below
const key = await createListenKey(config)
or else
you could simply do this
return createListenKey(config).then(res=>{
listenKey = res
})
can't say much more without knowing context.
Might I suggest not to mix then and async wait together
Because the createListenKey() function doesn't return anything. The return statement in the then clause inside that function is scoped in the then block. To return a value from an async function, you need to do something like this.
const createListenKey = async () => {
const response = await axios({
url: "/api/v3/userDataStream",
method: "POST",
baseURL: "https://api.binance.com",
headers: {
"X-MBX-APIKEY":
"H48w9CLuTtTi955qWjcjjEKhh0Ogb3jnnluYucXXXXXXXXXXXXXXXX",
},
})
var key = response.data.listenKey;
console.log(key, "created");
return key;
};

"Exit promise" with multiples fetch requests

I need to merge data from API. I do a first call to an endpoint that gives me a list of ids, then I do a request for each id. My goal is to return a list with the responses of all requests but I lost myself in promises ...
My code runs on NodeJS. Here is the code :
const fetch = require('node-fetch')
const main = (req, res) => {
fetch('ENDPOINT_THAT_GIVES_LIST_OF_IDS')
.then(response => response.json())
.then(response => {
parseIds(response)
.then(data => {
console.log(data)
res.json(data)
// I want data contains the list of responses
})
})
.catch(error => console.error(error))
}
const getAdditionalInformations = async function(id) {
let response = await fetch('CUSTOM_URL&q='+id, {
method: 'GET',
});
response = await response.json();
return response
}
const parseIds = (async raw_ids=> {
let ids= []
raw_ids.forEach(function(raw_id) {
let informations = {
// Object with data from the first request
}
let additionalInformations = await
getAdditionalInformations(raw_id['id'])
let merged = {...informations, ...additionalInformations}
ids.push(merged)
})
return ids
})
main()
I get this error : "await is only valid in async function" for this line :
let additionalInformations = await getAdditionalInformations(raw_id['id'])
Help me with promise and async/await please.
You're almost there, just a slight bit of error here with your parentheses:
// notice the parentheses'
const parseIds = async (raw_ids) => {
let ids= []
raw_ids.forEach(function(raw_id) {
let informations = {
// Object with data from the first request
}
let additionalInformations = await getAdditionalInformations(raw_id['id'])
let merged = {...informations, ...additionalInformations}
ids.push(merged)
})
return ids
}
You are missing an async after forEach
const parseIds = (async raw_ids=> {
let ids= []
raw_ids.forEach(async function(raw_id) {
let informations = {
// Object with data from the first request
}
let additionalInformations = await
getAdditionalInformations(raw_id['id'])
let merged = {...informations, ...additionalInformations}
ids.push(merged)
})
return ids
})
One suggestion: you are mixing promises (.then()) with async/await. Prefer async/await is more readable.
Note that getAdditionalInformations inside forEach doesn't wait for it to be done before going to the next entry of the array.
You can use plain old for(var i=0; .... instead

Categories