patternjavascriptMajor
Using fetch() and a new Promise object to get API results
Viewed 0 times
newfetchpromisegetusingandresultsobjectapi
Problem
I've written an ES6 function using the new fetch() API and returning a new resolved promise with a data object or a rejected promise with an error subclass.
I'm pretty new to both ES6 and Promises, and it looks a little unwieldy, so I'm wondering if there's a better way. I'm also wondering about how this relates to the "explicit promise construction antipattern".
Any suggestions for how to improve or simplify?
I'm pretty new to both ES6 and Promises, and it looks a little unwieldy, so I'm wondering if there's a better way. I'm also wondering about how this relates to the "explicit promise construction antipattern".
Any suggestions for how to improve or simplify?
function get(url) {
console.log('Making fetch() request to: ' + url);
let promise = new Promise((resolve, reject) => {
fetch(url).then(response => {
if (response.ok) {
const contentType = response.headers.get('Content-Type') || '';
if (contentType.includes('application/json')) {
response.json().then(obj => {
resolve(obj);
}, error => {
reject(new ResponseError('Invalid JSON: ' + error.message));
});
} else if (contentType.includes('text/html')) {
response.text().then(html => {
resolve({
page_type: 'generic',
html: html
});
}, error => {
reject(new ResponseError('HTML error: ' + error.message));
});
} else {
reject(new ResponseError('Invalid content type: ' + contentType));
}
} else {
if (response.status == 404) {
reject(new NotFoundError('Page not found: ' + url));
} else {
reject(new HttpError('HTTP error: ' + response.status));
}
}
}, error => {
reject(new NetworkError(error.message));
});
});
return promise;
}Solution
A few comments:
1)
Is pretty much the same as:
2) Keeping this in mind you can simplify your code with early returns and fewer branches:
1)
fetch already returns a promise, which means this:new Promise((resolve, reject) => {
return fetch(url).then(response => {
if (response.ok) {
resolve(response)
} else {
reject(new Error('error'))
}
}, error => {
reject(new Error(error.message))
})
})Is pretty much the same as:
fetch(url).then(response => {
if (response.ok) {
return response
}
return Promise.reject(Error('error'))
}).catch(error => {
return Promise.reject(Error(error.message))
})2) Keeping this in mind you can simplify your code with early returns and fewer branches:
function get(url) {
return fetch(url).then(response => {
if (response.ok) {
const contentType = response.headers.get('Content-Type') || '';
if (contentType.includes('application/json')) {
return response.json().catch(error => {
return Promise.reject(new ResponseError('Invalid JSON: ' + error.message));
});
}
if (contentType.includes('text/html')) {
return response.text().then(html => {
return {
page_type: 'generic',
html: html
};
}).catch(error => {
return Promise.reject(new ResponseError('HTML error: ' + error.message));
})
}
return Promise.reject(new ResponseError('Invalid content type: ' + contentType));
}
if (response.status == 404) {
return Promise.reject(new NotFoundError('Page not found: ' + url));
}
return Promise.reject(new HttpError('HTTP error: ' + response.status));
}).catch(error => {
return Promise.reject(new NetworkError(error.message));
});
}Code Snippets
new Promise((resolve, reject) => {
return fetch(url).then(response => {
if (response.ok) {
resolve(response)
} else {
reject(new Error('error'))
}
}, error => {
reject(new Error(error.message))
})
})fetch(url).then(response => {
if (response.ok) {
return response
}
return Promise.reject(Error('error'))
}).catch(error => {
return Promise.reject(Error(error.message))
})function get(url) {
return fetch(url).then(response => {
if (response.ok) {
const contentType = response.headers.get('Content-Type') || '';
if (contentType.includes('application/json')) {
return response.json().catch(error => {
return Promise.reject(new ResponseError('Invalid JSON: ' + error.message));
});
}
if (contentType.includes('text/html')) {
return response.text().then(html => {
return {
page_type: 'generic',
html: html
};
}).catch(error => {
return Promise.reject(new ResponseError('HTML error: ' + error.message));
})
}
return Promise.reject(new ResponseError('Invalid content type: ' + contentType));
}
if (response.status == 404) {
return Promise.reject(new NotFoundError('Page not found: ' + url));
}
return Promise.reject(new HttpError('HTTP error: ' + response.status));
}).catch(error => {
return Promise.reject(new NetworkError(error.message));
});
}Context
StackExchange Code Review Q#123577, answer score: 33
Revisions (0)
No revisions yet.