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!

0
kennycodes 16 grudzień 2019, 20:27
1
map() nie czeka na rozwiązanie obietnic przed przejściem do następnej iteracji. Sugerowałbym użycie biblioteki takiej jak bluebird do radzenia sobie z asynchronicznymi metodami gromadzenia
 – 
Michael Ossig
16 grudzień 2019, 20:29
Sposób w jaki twój kod jest tam napisany, firstAxiosCall powinien się zdarzyć, a potem secondAxiosCall, ahd, potem linia {data}, a potem if. Czekasz na wszystko właściwie. Podejrzewam, że Twój problem jest inny niż ten, który opisałeś
 – 
TKoL
16 grudzień 2019, 20:31
Wypróbuj const { data } = await secondAxiosCall;. Nie jestem pewien, czy to zadziała, ale nie zaszkodzi spróbować.
 – 
Ajay Dabas
16 grudzień 2019, 20:35
1
- Zwykłe pętle for wykonują await (wszystkie typy pętli for). To niezwykle przydatna funkcja. .forEach(), .map(), .filter() nie. Ale zwykłe pętle for to robią.
 – 
jfriend00
16 grudzień 2019, 20:39
1
- Funkcja współbieżności Bluebird w .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.
 – 
jfriend00
16 grudzień 2019, 20:48

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
  });
}
0
Gaspar Teixeira 16 grudzień 2019, 22:19