最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - async await fetch undefined. How to handle? - Stack Overflow

programmeradmin6浏览0评论

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('.jpg&text=.jpg');
      let promise2  = await fetch('.png&text=.png');
      let promise3  = await fetch('.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();

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./48x48/4caf50/ffffff.jpg&text=.jpg');
      let promise2  = await fetch('https://dummyimage./bad/url/here/48x48/e91e63/ffffff.png&text=.png');
      let promise3  = await fetch('https://dummyimage./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();

Share Improve this question edited May 29, 2020 at 6:40 suchislife asked May 26, 2020 at 17:11 suchislifesuchislife 1 7
  • 1 Try Promise.allSettled. It doesn't reject everything in the case where just one promise rejects (which is what Promise.all would do). Another note is that your fetches can't be parallel if you use await the way you are in your example. – zero298 Commented May 26, 2020 at 17:22
  • I see. Ok. So as for fetch being unable to be parallel... Argh! Youtube examples... Are you proposing I await the fetch and then await a json of the fetch? – suchislife Commented May 26, 2020 at 17:24
  • Updated code to reflect what I think you meant. – suchislife Commented May 26, 2020 at 17:30
  • 1 @suchislife, build the Promises into an array, and use a for await of loop to iterate on the Promises. That way you get the best of both worlds (depending on what you are trying to do) – user120242 Commented May 26, 2020 at 17:31
  • 1 I'm on FF 68 which doesn't support allSettled. I would put all the fetches into an array and use them there. It's OK to mix Promises and async/await. It's all about ease of use and trying to avoid callback hell. It lets us write synchronous looking code. – zero298 Commented May 26, 2020 at 17:47
 |  Show 2 more ments

2 Answers 2

Reset to default 5

Using Promise.allSettled you can run all the fetch calls in parallel and wait for them all to plete.

const test = async() => {
  const promise1  = await fetch('https://dummyimage./48x48/4caf50/ffffff.jpg&text=.jpg')
    .then(r => r.url)

  const promise2  = await fetch('https://dummyimage./bad/url/here/48x48/e91e63/ffffff.png&text=.png')
    .then(r => r.url)

  const promise3  = await fetch('https://dummyimage./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./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()

.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/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./${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
  };

}

发布评论

评论列表(0)

  1. 暂无评论