async await fetch undefined. How to handle?

拈花ヽ惹草 提交于 2020-06-11 22:47:39

问题


I am currently learning async await fetch and I've created the following example to help me learn.

The working example below:

  1. fetches three random json records from a Public API
  2. extracts the url from each return json
  3. creates three img elements
  4. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!