Mam komponent React, który wywołuje funkcję async
w componentDidUpdate
. Wewnątrz tej funkcji mam tablicę elementów, do których dzwonię Promise.all
. Jest jeden warunek, w którym wywołanie axios
jest wykonywane w zależności od tego, co zostało zwrócone z poprzedniego wywołania axios
. Problem, który mam polega na tym, że wywołanie axios
jest wykonywane przed zakończeniem wyników poprzedniego wywołania axios
i nie jestem pewien, dlaczego tak się dzieje.
Oto mój kod:
class Test extends Component {
this.state = {
experiments: []
}
async componentDidMount() {
await this.getExperiments(); // function to fetch experiments from a db
}
async componentDidUpdate() {
if (condition) {
await myFunction()
}
}
myFunction = async () => {
try {
const { experiments } = this.state;
const results = await Promise.all(experiments.map(async experiment => {
const firstAxiosCall = await axios.get(someUrl);
const secondAxiosCall = await axios.get(anotherUrl)
const { data } = secondAxiosCall; // THIS IS WHERE BUG OCCURS
if (data.length === 0) { // For one experiment, this is not empty, but it still goes into the if statement.
await axios.post(thirdUrl)
}
}));
} catch (e) {
console.log('ERROR', e);
}
}
}
Wiem, że jest to błąd, ponieważ wywołanie axios
wewnątrz instrukcji if jest wywoływane i pojawia się błąd db na moim zapleczu informujący, że nic nie zostało przekazane. Chcę, aby dane z drugiego wywołania axios najpierw wróciły kontynuowanie instrukcji if. Czy jest coś, co robię źle?
Mam nadzieję, że to wystarczająca ilość informacji!
Dziękuję wam wszystkim!
1 odpowiedź
Sugerowałbym użycie czegoś takiego:
myFunction = async () => {
await axios.all([
axios.get('http://someurl.com'),
axios.get('http://anotherurl.com')
])
.then(axios.spread((someUrlRest, anotherUrlRes) => {
// do something with both responses
});
}
map()
nie czeka na rozwiązanie obietnic przed przejściem do następnej iteracji. Sugerowałbym użycie biblioteki takiej jakbluebird
do radzenia sobie z asynchronicznymi metodami gromadzeniafirstAxiosCall
powinien się zdarzyć, a potemsecondAxiosCall
, ahd, potem linia{data}
, a potemif
. Czekasz na wszystko właściwie. Podejrzewam, że Twój problem jest inny niż ten, który opisałeśconst { data } = await secondAxiosCall;
. Nie jestem pewien, czy to zadziała, ale nie zaszkodzi spróbować.for
wykonująawait
(wszystkie typy pętlifor
). To niezwykle przydatna funkcja..forEach()
,.map()
,.filter()
nie. Ale zwykłe pętlefor
to robią..map()
jest nadal bardzo przydatna. Ale uważam, że już nie potrzebuję tego na wiele więcej. Chciałbym zobaczyć, jak JavaScript dodaje kilka iteracji tablic uwzględniających obietnicę. Podstawa jest już dostępna z asyncIteratorami.