【问题标题】:async await fetch undefined. How to handle?异步等待获取未定义。如何处理?
【发布时间】:2020-09-13 14:00:32
【问题描述】:

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

下面的工作示例:

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

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

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

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

【问题讨论】:

  • 试试Promise.allSettled。在只有一个 promise 拒绝的情况下,它不会拒绝所有内容(Promise.all 会这样做)。另一个注意事项是,如果您按照示例中的方式使用 await,则您的 fetches 不能并行。
  • 我明白了。好的。至于fetch 无法并行……啊! Youtube 示例...你是在提议我 await fetch 然后 await json fetch 吗?
  • 更新了代码以反映我认为您的意思。
  • @suchislife,将 Promises 构建成一个数组,并使用 for await 循环来迭代 Promises。这样你就可以两全其美(取决于你想要做什么)
  • 我在 FF 68 上,它不支持 allSettled。我会将所有fetches 放入一个数组并在那里使用它们。可以将 Promises 和 async/await 混合使用。这一切都与易用性有关,并试图避免回调地狱。它让我们可以编写同步 looking 代码。

标签: javascript promise async-await


【解决方案1】:

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

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

}

【讨论】:

    【解决方案2】:

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

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

    对于较旧的支持,您需要使用一个可以从 fetch 中捕获任何错误的 Promise。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-02
      • 2020-05-30
      • 1970-01-01
      • 2017-06-08
      • 2019-01-17
      相关资源
      最近更新 更多