英文:
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'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**
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>
# 答案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("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);
// 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) => r.blob()));
data.forEach((d) => {
const img = document.createElement("img");
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) => console.error(err);
}
};
firstImages(15);
Good luck!!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论