my aim is to fetch data from two URLs and perform an action only when both have e back successfully. On the other hand i want to return an error if either of them fail. I have played around with my code and managed to get the desired effect.
My question is, is there a more efficient, succinct way of achieving the same functionality?
Helper functions
let status = (r) => {
if (r.ok) {
return Promise.resolve(r)
} else {
return Promise.reject(new Error(r.statusText))
}
}
let json = (r) => r.json();
Requests
let urls = [
'http://localhost:3000/inplete',
'http://localhost:3000/plete'
]
let promises = urls.map(url => {
return fetch(url)
.then(status)
.then(json)
.then(d => Promise.resolve(d))
.catch(e => Promise.reject(new Error(e)));
});
Promise.all(promises).then(d => {
// do stuff with d
}).catch(e => {
console.log('Whoops something went wrong!', e);
});
my aim is to fetch data from two URLs and perform an action only when both have e back successfully. On the other hand i want to return an error if either of them fail. I have played around with my code and managed to get the desired effect.
My question is, is there a more efficient, succinct way of achieving the same functionality?
Helper functions
let status = (r) => {
if (r.ok) {
return Promise.resolve(r)
} else {
return Promise.reject(new Error(r.statusText))
}
}
let json = (r) => r.json();
Requests
let urls = [
'http://localhost:3000/inplete',
'http://localhost:3000/plete'
]
let promises = urls.map(url => {
return fetch(url)
.then(status)
.then(json)
.then(d => Promise.resolve(d))
.catch(e => Promise.reject(new Error(e)));
});
Promise.all(promises).then(d => {
// do stuff with d
}).catch(e => {
console.log('Whoops something went wrong!', e);
});
Share
Improve this question
asked Jun 22, 2017 at 7:52
SamuelSamuel
2,6356 gold badges34 silver badges41 bronze badges
7
-
3
If your code works then codereview.stackexchange. might be a better place to ask. At a first glance the
.then(d => Promise.resolve(d))
and.catch(e => Promise.reject(new Error(e)));
lines seem unnecessary (they don't do anything that wouldn't already happen). Also thestatus
function could just beif (r.ok) { return r; } else {throw new Error(r.statusText); }
. No need to create promises where they are not necessary. – Felix Kling Commented Jun 22, 2017 at 7:59 - Inside your map function don't call "then" and the likes just return fetch(url) – Paul Okeke Commented Jun 22, 2017 at 8:00
-
@FelixKling thanks! i had no idea that site existed! Brilliant, i have reduced that line down to
let promises = urls.map(url => fetch(url).then(status).then(json));
– Samuel Commented Jun 22, 2017 at 8:12 -
@PaulOkeke If i just return
fetch(url)
inmap
then how can i check my response was okay? – Samuel Commented Jun 22, 2017 at 8:13 - @Samuel you will check each of all the response in Promises.all . e.g Promises.all (promises).then(allfetch => { allfetch [0], allfetch [1].... }) . Promise.all will automatically invoke the "then" function on all the promises and the results of all the promises are returned as an array un the order they were added. Im currently typing with my phone... you can check the docs. developer.mozilla/en/docs/Web/JavaScript/Reference/… – Paul Okeke Commented Jun 22, 2017 at 16:12
3 Answers
Reset to default 5
// https://jsonplaceholder.typicode. - Provides test JSON data
var urls = [
'https://jsonplaceholder.typicode./todos/1',
'https://jsonplaceholder.typicode./todos/2',
'https://jsonplaceholder.typicode./posts/1',
'https://jsonplaceholder.typicode./posts/2'
];
// Maps each URL into a fetch() Promise
var requests = urls.map(function(url){
return fetch(url)
.then(function(response) {
// throw "uh oh!"; - test a failure
return response.json();
})
});
// Resolve all the promises
Promise.all(requests)
.then((results) => {
console.log(JSON.stringify(results, null, 2));
}).catch(function(err) {
console.log("returns just the 1st failure ...");
console.log(err);
})
<script src="https://getfirebug./firebug-lite-debug.js"></script>
const urls = [
'http://localhost:3000/inplete',
'http://localhost:3000/plete'
]
const json = (r) => r.json()
const status = (r) => r.ok ? Promise.resolve(r) : Promise.reject(new Error(r.statusText))
const toRequest = url => fetch(url).then(status).then(json)
const onError = e => { console.log('Whoops something went wrong!', e) }
const consumeData = data => { console.log('data: ', data) }
Promise.all(urls.map(toRequest))
.then(consumeData)
.catch(onError)
Use fetchOk for nicer error messages, and destructuring to access the results:
let fetchOk = (...args) => fetch(...args)
.then(res => res.ok ? res : res.json().then(data => {
throw Object.assign(new Error(data.error_message), {name: res.statusText});
}));
Promise.all([
'http://localhost:3000/inplete',
'http://localhost:3000/plete'
].map(url => fetchOk(url).then(r => r.json()))).then(([d1, d2]) => {
// do stuff with d1 and d2
}).catch(e => console.error(e));
// Work around stackoverflow's broken error logger.
var console = { error: msg => div.innerHTML += msg + "<br>" };
<div id="div" style="white-space: pre;"></div>