Promise pattern falling back multiple fetches - javascript

I'm using fetch promises to fall back through 3 API calls until one succeeds. I'm not sure what the best pattern is for that. I'd like to use something like this, where promise rejection is handled by the next catch and fetches the next URL.
The issue is that successfully resolved data is picked up by .then(res => res.json())
fetch(url1)
.then(res => res.json())
.then(data => {
if (data.status !== 'OK') {
return Promise.reject()
}
return Promise.resolve(data)
})
.then(null, () => {
return fetch(url2)
})
.then(res => res.json())
.then(data => {
if (!data.success) {
return Promise.reject()
}
return Promise.resolve(data)
})
.then(null, () => {
return fetch(url3)
})
.then(res => res.json())
.then(data => {
if (data.error) {
return Promise.reject()
}
return Promise.resolve(data)
})
The success checks are different for each function, so I can't easily use a loop that breaks on success.

Just group the optional API call and processing in the catch function:
fetch(url1)
.then(res => res.json())
.then(data => {
if (data.status !== 'OK') {
return Promise.reject()
}
return Promise.resolve(data)
}).catch(function() {
return fetch(url2)
.then(res => res.json())
.then(data => {
if (!data.success) {
return Promise.reject()
}
return Promise.resolve(data)
});
}).catch(function() {
return fetch(url3)
.then(res => res.json())
.then(data => {
if (data.error) {
return Promise.reject()
}
return Promise.resolve(data)
})
});

You could use Promise.all or Promise.race, and wrap the checks on functions.

Related

How to resolve multiple then() promise into one

In this code I used multiple then() methods, I just want to convert it into only one then, How it is possible.
getGreeting = () => {
fetch(url)
.then((response) => response.json())
.then((result) => result.data)
.then((data) => printCards(data))
.catch((err) => {
console.log(err);
});
};
notice the async and await keywords
fetch(url)
.then(async (response) => {
const json = await response.json();
printCards(json.data);
})
.catch((err) => {
console.log(err);
});
};

How to call multiple fetch APIs

I have to make a fetch call at a url and after getting its response I want to use those results to call another fetch. I have following code:-
async function getDate(request) {
let data;
console.log('handle request called')
await fetch('<first-url>')
.then(res => {
let urls = res.json()
console.log('urls are ', urls)
return urls.data
})
.then((urls) => {
let url = urls[0]
console.log('url is ', url)
return fetch(url)
})
.then((res) => {
data = res.body
})
.catch(() => {
console.log("something went wrong")
})
return new Response(data, {
headers: { 'content-type': 'text/html' },
})
}
I followed the above method after following this tutorial. However it does not seem to work and I am getting urls are {Promise:[Pending]}.
Here issue with return res.json(). res.json() is promisable object, so u have to resolve it to get data.
For your example:
const fetch = require("node-fetch");
async function getDate() {
let data;
console.log("handle request called");
return await fetch('<first-url>')
.then((res) => res.json())
.then((urls) => {
console.log("urls are ", urls);
if (urls.length)
return Promise.all(urls.map((url) => fetch(url).then((x) => x.json())));
return [];
})
.then((responses) => {
console.log("urls are ", responses);
return responses;
});
}
getDate().then(console.log);
Sample:
async function getDate() {
let data;
console.log("handle request called");
return await fetch("https://api.covid19api.com/countries")
.then((res) => res.json())
.then((urls) => {
console.log("urls are ", urls);
return urls;
});
}
getDate().then(console.log);

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();
});

The second and consequent then are not working

Only the first then is working. Every subsequent then is not working.
export const usersFetchData = (url) => {
return (dispatch) => {
dispatch(userIsLoading(true));
axios
.get(url)
.then(res => {
if(!res.ok){
throw Error(res.statusText)
}
dispatch(userIsLoading(false));
console.log(res.data);
return res;
})
.then(res => res.json())
.then(users => {
console.log(users);
dispatch(usersFetchDataSuccess(users))})
.catch(() => dispatch(userHasErrored(true)));
}
}
axios converts it into JSON for you, you don't have to do it yourself like you do in fetch
export const usersFetchData = (url) => {
return (dispatch) => {
dispatch(userIsLoading(true));
axios
.get(url)
.then(res => {
if(!res.ok){
throw Error(res.statusText)
}
dispatch(userIsLoading(false));
console.log(res.data);
return res.data; // returning the json respone
})
//.then(res => res.json()) // removed this, you don't need it
.then(users => {
console.log(users);
dispatch(usersFetchDataSuccess(users))
})
.catch(() => dispatch(userHasErrored(true)));
}
}

Categories