I want to make 15 concurrent calls to an API using Promise.all( ) rather than successive calls. I can't figure out what I am doing wrong

huangapple go评论60阅读模式
英文:

I want to make 15 concurrent calls to an API using Promise.all( ) rather than successive calls. I can't figure out what I am doing wrong

问题

这是您要翻译的内容:

Caveat: I'm learning to work with JavaScript Promises and API calls, so I try to write the code in promise.then format as well as async / await, so I know how to use both.

I have a container that I am initially filling with images from 15 successive API calls; each call returns a single image. As scrolling happens, more API calls are made. I am able to make everything work with straightforward Promises as well as async / await.

I am trying to rewrite the API calls to make them concurrent rather than successive. My new code doesn't work - depending on what I've done, I get no result (and no error in my console) or a typeError of undefined. I don't know what I am doing wrong.

This is the code that is working - in both formats (not including the page load code and intersectionObserver)

**promises only**
```javascript
const getImage = function () {
  fetch("https://api.api-ninjas.com/v1/randomimage", {
    method: "GET",
    headers: {
      "X-API-Key": "###",
      Accept: "image/jpg", 
    },
  })
    .then((response) => {
      if (!response.ok) throw new Error("Network failure"); 
      return response.blob();
    })
    .then((blob) => {
      const img = document.createElement("img");
      img.src = URL.createObjectURL(blob);
      container.append(img);
    })
    .catch((err) => console.error(`${err.message}`));
};

async / await

const getImage = async function () {
  try {
    const response = await fetch("https://api.api-ninjas.com/v1/randomimage/", {
      method: "GET",
      headers: {
        "X-API-Key": "###",
        Accept: "image/jpg", 
      },
    });
    if (!response.ok)
      throw new Error(`Network failure! Status: ${response.status}`); 

    const data = await response.blob();
    const img = document.createElement("img");
    img.src = URL.createObjectURL(data);
    container.append(img);
  } catch {
    (err) => console.error(`${err.message}`);
  }
};

This is what I am trying for concurrent calls; I am calling the function after disabling all my other page load code just to see if it's working at all. Nothing loads on my page and I get no error or TypeError in my console.

const getImage = function () {
  fetch("https://api.api-ninjas.com/v1/randomimage", {
    method: "GET",
    headers: {
      "X-API-Key": "###",
      Accept: "image/jpg", 
    },
  });
};

const firstImages = async function () {
  try {
    const res = await Promise.all([
      getImage(),
      getImage(),
      getImage(),
      getImage(),
      getImage(),
      getImage(),
      getImage(),
      getImage(),
      getImage(),
      getImage(),
      getImage(),
      getImage(),
      getImage(),
      getImage(),
      getImage(),
    ]);
    const data = await Promise.all(res.forEach((r) => r.blob()));
    console.log(data);
    data.forEach((d) => {
      const img = document.createElement("img");
      img.src = URL.createObjectURL(d);
      container.append(img);
    });
  } catch {
    (err) => console.error(`${err.message}`);
  }
};

firstImages();

<details>
<summary>英文:</summary>

Caveat: I&#39;m learning to work with JavaScript Promises and API calls, so I try to write the code in promise.then format as well as async / await, so I know how to use both.

I have a container that I am initially filling with images from 15 successive API calls; each call returns a single image. As scrolling happens, more API calls are made. I am able to make everything work with straightforward Promises as well as async / await. 

I am trying to rewrite the API calls to make them concurrent rather than successive. My new code doesn&#39;t work - depending on what I&#39;ve done, I get no result (and no error in my console) or a typeError of undefined. I don&#39;t know what I am doing wrong.

This is the code that is working - in both formats (not including the page load code and intersectionObserver)


**promises only**

const getImage = function () {
fetch("https://api.api-ninjas.com/v1/randomimage", {
method: "GET",
headers: {
"X-API-Key": "###",
Accept: "image/jpg",
},
})
.then((response) => {
if (!response.ok) throw new Error("Network failure");
return response.blob();
})
.then((blob) => {
const img = document.createElement("img");
img.src = URL.createObjectURL(blob);
container.append(img);
})
.catch((err) => console.error(${err.message}));
};


**async / await**

const getImage = async function () {
try {
const response = await fetch("https://api.api-ninjas.com/v1/randomimage/", {
method: "GET",
headers: {
"X-API-Key": "###",
Accept: "image/jpg",
},
});
if (!response.ok)
throw new Error(Network failure! Status: ${response.status});

const data = await response.blob();
const img = document.createElement(&quot;img&quot;);
img.src = URL.createObjectURL(data);
container.append(img);

} catch {
(err) => console.error(${err.message});
}
};


This is what I am trying for concurrent calls; I am calling the function after disabling all my other page load code just to see if it&#39;s working at all. Nothing loads on my page and I get no error or TypeError in my console.

const getImage = function () {
fetch("https://api.api-ninjas.com/v1/randomimage", {
method: "GET",
headers: {
"X-API-Key": "###",
Accept: "image/jpg",
},
});
};

const firstImages = async function () {
try {
const res = await Promise.all([
getImage(),
getImage(),
getImage(),
getImage(),
getImage(),
getImage(),
getImage(),
getImage(),
getImage(),
getImage(),
getImage(),
getImage(),
getImage(),
getImage(),
getImage(),
]);
const data = await Promise.all(res.forEach((r) => r.blob()));
console.log(data);
data.forEach((d) => {
const img = document.createElement("img");
img.src = URL.createObjectURL(d);
container.append(img);
});
} catch {
(err) => console.error(${err.message});
}
};

firstImages();


</details>


# 答案1
**得分**: 0

以下是代码的翻译部分:

```javascript
const getImage = function () {
  // 首先,正如Andy在注释中写的那样,返回fetch请求
  return fetch("https://api.api-ninjas.com/v1/randomimage", {
    method: "GET",
    headers: {
      "X-API-Key": "###",
      Accept: "image/jpg", 
    },
  });
};

const firstImages = async function (numberOfImages = 1) {
  try {
    const fetchArr = [];

    let i = 0;
    while (i <= numberOfImages) {
      fetchArr.push(getImage());
      i++;
    }

    const res = await Promise.all(fetchArr);

    // 正如另一个评论中所指出的,使用map方法,因为它会返回Promise.all可以迭代的数组。
    const data = await Promise.all(res.map((r) => r.blob()));

    data.forEach((d) => {
      const img = document.createElement("img");
      img.src = URL.createObjectURL(d);
      container.append(img);
    });
  } catch {
    // 可能最好的做法(正如Keith评论中所述)是将错误对象传递给console.error。这样做会打印一些通常在发生问题时值得关注的额外信息。
    (err) => console.error(err);
  }
};

firstImages(15);

祝好运!

英文:

Let me try to help you out a bit. Also added a small loop so you can decide how many images you actually want to bring out.
See comments in code as well:

const getImage = function () {
  // Firstly, as Andy wrote in comments, return the fetch
  return fetch(&quot;https://api.api-ninjas.com/v1/randomimage&quot;, {
    method: &quot;GET&quot;,
    headers: {
      &quot;X-API-Key&quot;: &quot;###&quot;,
      Accept: &quot;image/jpg&quot;, 
    },
  });
};

const firstImages = async function (numberOfImages = 1) {
  try {
    const fetchArr = [];

    let i = 0;
    while (i &lt;= numberOfImages) {
      fetchArr.push(getImage());
      i++;
    }

    const res = await Promise.all(fetchArr);

    // As was pointed out by another comment, use map here, as it will return an array that the Promise.all can iterate over.
    const data = await Promise.all(res.map((r) =&gt; r.blob()));

    data.forEach((d) =&gt; {
      const img = document.createElement(&quot;img&quot;);
      img.src = URL.createObjectURL(d);
      container.append(img);
    });
  } catch {
    // Probably best (as Keith commented) to just pass the error object to the console.error. It will print a few extra things that are normally noteworthy when tragedy strikes
    (err) =&gt; console.error(err);
  }
};

firstImages(15);

Good luck!!

huangapple
  • 本文由 发表于 2023年6月29日 17:04:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/76579602.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定