简体   繁体   English

如何使用带有 fetch 和 Promise.all 的循环?

[英]How to use loops with fetch and Promise.all?

So I was following along an MDN article on promises and was wondering how to modify the following code to be able to work for any number of files (not just 3).所以我关注了一篇关于 Promise 的 MDN 文章,想知道如何修改以下代码以适用于任意数量的文件(不仅仅是 3 个)。

function fetchAndDecode(url) {
  return fetch(url).then(response => {
    if(!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    } else {
      if(response.headers.get("content-type") === "image/jpeg") {
        return response.blob();
      } else if(response.headers.get("content-type") === "text/plain") {
        return response.text();
      }
    }
  })
  .catch(e => {
    console.log(`There has been a problem with your fetch operation for resource "${url}": ` + e.message);
  })
  .finally(() => {
    console.log(`fetch attempt for "${url}" finished.`);
  })
}

let coffee = fetchAndDecode('coffee.jpg');
let tea = fetchAndDecode('tea.jpg');
let description = fetchAndDecode('description.txt');

Promise.all([coffee, tea, description]).then(values => {
  console.log(values);
  // Store each value returned from the promises in separate variables; create object URLs from the blobs
  let objectURL1 = URL.createObjectURL(values[0]);
  let objectURL2 = URL.createObjectURL(values[1]);
  let descText = values[2];

  // Display the images in <img> elements
  let image1 = document.createElement('img');
  let image2 = document.createElement('img');
  image1.src = objectURL1;
  image2.src = objectURL2;
  document.body.appendChild(image1);
  document.body.appendChild(image2);

  // Display the text in a paragraph
  let para = document.createElement('p');
  para.textContent = descText;
  document.body.appendChild(para);
});

MDN specifically notes that "If you were improving this code, you might want to loop through a list of items to display, fetching and decoding each one, and then loop through the results inside Promise.all(), running a different function to display each one depending on what the type of code was. This would make it work for any number of items, not just three." MDN 特别指出“如果您正在改进此代码,您可能希望循环显示要显示的项目列表、获取和解码每个项目,然后在 Promise.all() 中遍历结果,运行不同的 function 以显示每个都取决于代码的类型。这将使它适用于任意数量的项目,而不仅仅是三个。 I'm not sure how to do this though, and would appreciate help.我不知道如何做到这一点,并希望得到帮助。 Thanks.谢谢。

The second part of the code could be generalised as follows:代码的第二部分可以概括如下:

let urls = ['coffee.jpg', 'tea.jpg', 'description.txt'];

Promise.all(urls.map(fetchAndDecode)).then(values => {
    let elem;
    for (let value of values) {
        if (value instanceof Blob) {
            elem = document.createElement('img');
            elem.src = URL.createObjectURL(value);
        } else if (typeof value === "string") {
            elem = document.createElement('p');
            elem.textContent = value;
        } else {
            console.log("unexpected value type");
            continue;
        }
        document.body.appendChild(elem);
    }
});
const resources = ['coffee.jpg', 'tea.jpg', 'description'];

const resourceRequests = resources.map(fetchAndDecode);

Promise.all(resourceRequests.then(values => {

...

Is one way to implement the suggestion.是实施建议的一种方式。 This approach allows for easier modification of the list of resources, but doesn't really change any of the Promise code.这种方法可以更轻松地修改资源列表,但不会真正更改任何 Promise 代码。

The .map code above is equivalent to (resource => fetchAndDecode(resource)) since fetchAndDecode takes only the first argument that .map would pass to it.上面的.map代码等价于 (resource => fetchAndDecode(resource)) 因为fetchAndDecode只接受.map将传递给它的第一个参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM