问题
I am currently learning async await fetch
and I've created the following example to help me learn.
The working example below:
- fetches three random json records from a Public API
- extracts the
url
from each returnjson
- creates three
img
elements - appends three
img
elements to the document body.
Notice that promise2
has an intentionally wrong path set to force a http status 404.
How do I handle this error if it was to happen to any of the three promises?
// the big promise.
async function getAsyncData() {
try {
// attempt to resolve 3 individual unrelated promises...
let promise1 = await fetch('https://dummyimage.com/48x48/4caf50/ffffff.jpg&text=.jpg');
let promise2 = await fetch('https://dummyimage.com/bad/url/here/48x48/e91e63/ffffff.png&text=.png');
let promise3 = await fetch('https://dummyimage.com/48x48/00bcd4/ffffff.gif&text=.gif');
// we create an html img element and set its src attribute to the thumbnailUrl...
var img = document.createElement('img');
img.src = promise1.url;
// ...and add it to our html document body...
document.body.append(img);
// we create an html img element and set its src attribute to the thumbnailUrl...
var img = document.createElement('img');
img.src = promise2.url;
// ...and add it to our html document body...
document.body.append(img);
// we create an html img element and set its src attribute to the thumbnailUrl...
var img = document.createElement('img');
img.src = promise3.url;
// ...and add it to our html document body...
document.body.append(img);
} catch (error) {
console.log('Try/Catch block error:', error);
}
// return {
// }
}
getAsyncData();
回答1:
Using Promise.allSettled you can run all the fetch calls in parallel and wait for them all to complete.
const test = async() => {
const promise1 = await fetch('https://dummyimage.com/48x48/4caf50/ffffff.jpg&text=.jpg')
.then(r => r.url)
const promise2 = await fetch('https://dummyimage.com/bad/url/here/48x48/e91e63/ffffff.png&text=.png')
.then(r => r.url)
const promise3 = await fetch('https://dummyimage.com/48x48/00bcd4/ffffff.gif&text=.gif')
.then(r => r.url)
const results = await Promise.allSettled([promise1, promise2, promise3])
console.log(results);
}
test();
For older support you would need to use a promise that would catch any errors from the fetch.
function makeCall () {
return new Promise((resolve) => {
fetch('https://dummyimage.com/48x48/4caf50/ffffff.jpg&text=.jpg')
.then(r => console.log(r.url))
.catch(error => resolve({ error }))
})
}
const test = async() => {
const promise1 = makeCall()
const promise2 = makeCall()
const promise3 = makeCall()
const results = await Promise.all([promise1, promise2, promise3])
console.log(results)
}
test()
回答2:
@suchislife: That answer you posted should be a separate question honestly. I've flagged it, because it's actually a separate question. This is unrelated to your original question about getting undefined
. I'm only posting this here to interim answer your problem, but you should accept escapello's answer and this should be a different thread. Allowing stuff like this would clutter up StackOverflow.
@Moderators: Actually I'm just now noticing @suchislife mentioned handling 404, but never explicitly stated or showed in your code that your goal was to catch 404 errors, and your question was about a separate error. I'm not sure how that should be treated. I guess that sort of counts as being part of the question?
.error and try/catch is not what you are looking for:
fetch resolves even if 404?
You need to check the value of response.ok
. fetch only throws errors on network problems, not error responses.
// Background Colors
const bgHexColors = ['f44336', 'e91e63', '9c27b0', '673ab7', '3f51b5', '2196f3', '03a9f4', '00bcd4', '009688', '4caf50', '8bc34a', 'cddc39', 'ffeb3b', 'ffc107', 'ff9800', 'ff5722', '795548', '9e9e9e', '607d8b'];
// Foreground Colors
const fgHexColors = ['ffffff'];
// Image File Extensions
const imgExtensions = ['.png', '.gif', '.jpg'];
// First, we initialize an empty array for promises.
let myPromises = [];
// We then populate this array with 24 promises.
for(let i = 0; i < 24; i++){
let imgWidth = 48;
let imgHeight = 48;
let bgHexColor = bgHexColors[Math.floor(Math.random() * bgHexColors.length)];
let fgHexColor = fgHexColors[Math.floor(Math.random() * fgHexColors.length)];
let imgExtension = imgExtensions[Math.floor(Math.random() * imgExtensions.length)];
let imgText = imgExtension;
// We declare the promise to be added and...
let myPromise = getRandomImage(imgWidth, imgHeight, bgHexColor, fgHexColor, imgExtension, imgText);
// add each promise to the myPromises array.
myPromises.push(myPromise);
}
// We create an html span element and...
let span = document.createElement('span');
span.style.color = '#ffffff';
// We set the element's span text to Please wait...
span.innerText = 'Please wait...';
// We add the span element to the document body.
document.body.append(span);
// Promise.all requires an array.
Promise.all(myPromises).then((myResponses) => {
// debug
// console.log(myResponses);
// We create an html img element and...
let span = document.createElement('span');
span.style.color = '#ffffff';
// We set the element's span text to Please wait...
span.innerText = 'Done.';
// We add the span element to the document body.
document.body.append(span);
// We create an html img element and...
let br = document.createElement('br');
// We add the br element to the document body.
document.body.append(br);
// for each promise resolved...
for(let i = 0; i < myResponses.length; i++) {
// We check its returned object containing the resolverImg...
if(myResponses[i].resolverImg !== null) {
// We create an html img element and...
let img = document.createElement('img');
// We set the element's image source to the resolverImg url returned and..
img.src = myResponses[i].resolverImg;
// We add the img element to the document body.
document.body.append(img);
}
}
}).catch(err => console.error(err));
// The individual Promise.
// Accepts 5 arguments; image size, background color, foreground color, image file extension, image text.
async function getRandomImage(imgWidth, imgHeight, bgHexColor, fgHexColor, imgExt, imgText) {
// The Response interface of the Fetch API represents the response to a request.
// https://developer.mozilla.org/en-US/docs/Web/API/Response
// We initialize the image and status as null...
let myResolverImg = null;
let myResolverStatus = null;
// We use a Try/Catch block to check if the resolverImg exists...
try {
// We create a fetch async resolver...
let myResolver = await fetch(`https://dummyimage.com/${imgWidth}x${imgHeight}/${bgHexColor}/${fgHexColor}${imgExt}&text=${imgText}`);
// debug
// console.log(myResolver);
if(myResolver.ok) {
// if it exists, change it from null to a valid image url path.
myResolverImg = myResolver.url;
myResolverStatus = myResolver.status;
}
} catch (err) {
// if fetch network error...
console.error('Fetch network error.');
}
// Return js object containing image url OR, resolverImg REMAINS null as initially declared.
return {
resolverImg: myResolverImg,
resolverStatus: myResolverStatus
};
}
来源:https://stackoverflow.com/questions/62027691/async-await-fetch-undefined-how-to-handle