异步等待获取未定义。如何处理?

时间:2020-05-26 17:11:05

标签: javascript promise async-await

我目前正在学习async await fetch,并且创建了以下示例来帮助我学习。

下面的工作示例:

  1. 从公共API提取三个随机json记录
  2. 从每次返回url中提取json
  3. 创建三个img元素
  4. 在文档正文中附加三个img元素。

请注意,promise2的路径故意设置为强制http状态404。

如果这三个诺言中的任何一个发生了错误,我该如何处理?

// 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();

2 个答案:

答案 0 :(得分:4)

使用Promise.allSettled,您可以并行运行所有访存调用,并等待它们全部完成。

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();

对于较早的支持,您将需要使用一个承诺,该承诺将捕获提取中的所有错误。

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()

答案 1 :(得分:1)

@suchislife:老实说,您发布的答案应该是一个单独的问题。我已将其标记出来,因为它实际上是一个单独的问题。这与您最初关于获取undefined的问题无关。我仅在此处发布此内容以临时回答您的问题,但是您应该接受escapello的回答,这应该是不同的主题。允许这样的事情会使StackOverflow混乱。

@Moderators:实际上,我刚才注意到@suchislife提到了处理404,但从未明确声明或在您的代码中表明您的目标是捕获404错误,而您的问题是关于一个单独的错误。我不确定应该如何对待。我猜这是问题的一部分吗?

.error和try / catch不是您要的内容: fetch resolves even if 404?
您需要检查response.ok的值。提取只会在网络问题上引发错误,而不是错误响应。

// 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
  };

}