问题
I have a list of data that I am sending to google cloud. My current code looks like this:
const teams = ['LFC', 'MUFC', 'CFC'];
teams.forEach(team => {
fetch({
url: URL,
method: 'PUT',
body: team
});
})
This works with one team
but it is timing out if sending multiple files and the files are bigger. I am sending images over and not strings. To solve this I need to POST
the data one file by one, and wait for the previous POST
to complete before sending the subsequent one. Can anyone advise the best way of doing this?
Worth noting that I don't have any control over the number of files that are uploaded.
回答1:
Use a reduce
instead of forEach
, with .then()
.
The following will store the promise of the last fetch
in acc
(the accumulator parameter of reduce
), and appends the new fetch
inside of a then
listener, to ensure that the previous fetch
is finished:
const teams = ['LFC', 'MUFC', 'CFC'];
teams.reduce((acc,team) => {
return acc.then(()=>{
return fetch({
url: URL,
method: 'PUT',
body: team
});
})
}, Promise.resolve())
.then(()=>console.log("Everything's finished"))
.catch(err=>console.error("Something failed:",err))
//Simulate fetch:
const fetch = team => new Promise(rs => setTimeout(() => {rs();console.log(team)}, 1000))
const teams = ['LFC', 'MUFC', 'CFC'];
teams.reduce((acc, team) => {
return acc.then(() => {
return fetch({
url: URL,
method: 'PUT',
body: team
});
})
}, Promise.resolve())
.then(() => console.log("Everything's finished"))
.catch(err => console.error("Something failed:", err))
Or, even better, if you can, use async/await
(it's more readable):
const teams = ['LFC', 'MUFC', 'CFC'];
async function upload(teams){
for(const team of teams){
await fetch({
url: URL,
method: 'PUT',
body: team
});
}
}
upload(teams)
.then(()=>console.log("Everything's finished"))
.catch(err=>console.error("Something failed:",err))
//Simulate fetch:
const fetch = team => new Promise(rs => setTimeout(() => {rs();console.log(team)}, 1000))
const teams = ['LFC', 'MUFC', 'CFC'];
async function upload(teams) {
for (const team of teams) {
await fetch({
url: URL,
method: 'PUT',
body: team
});
}
}
upload(teams)
.then(() => console.log("Everything's finished"))
.catch(err => console.error("Something failed:", err))
回答2:
You can use async/await with a for...of loop. Each call will "hold" the loop, until it's done, and then the loop will continue the next call:
const teams = ['LFC', 'MUFC', 'CFC'];
async function send(teams) {
for (const team of teams) {
await fetch({
url: URL,
method: 'PUT',
body: team
});
}
}
回答3:
You can make use of async/await, as follows:
const teams = ['LFC', 'MUFC', 'CFC'];
teams.forEach(async (team) => {
await fetch({
url: URL,
method: 'PUT',
body: team
});
})
来源:https://stackoverflow.com/questions/58492609/wait-for-one-fetch-to-finish-before-starting-the-next