Async / Inside Array#map()

Dostaję błąd czasu kompilacji z tym kodem:

const someFunction = async (myArray) => {
    return myArray.map(myValue => {
        return {
            id: "my_id",
            myValue: await service.getByValue(myValue);
        }
    });
};

Komunikat o błędzie to:

Wait is a reserved word

Dlaczego nie mogę tego tak użyć?

Próbowałem też w inny sposób, ale to daje mi ten sam błąd:

 const someFunction = async (myArray) => {
    return myArray.map(myValue => {
        const myNewValue = await service.getByValue(myValue);
        return {
            id: "my_id",
            myValue: myNewValue 
        }
    });
};
Author: Felix Kling, 2017-02-27

3 answers

Nie możesz tego zrobić tak, jak sobie wyobrażasz, ponieważ nie możesz użyć await, jeśli nie znajduje się bezpośrednio wewnątrz async funkcji.

Sensownym rozwiązaniem byłoby przeniesienie funkcji do map asynchronicznej. Oznacza to, że map zwróci szereg obietnic. Możemy wtedy użyć Promise.all, aby uzyskać wynik, gdy wszystkie obietnice powrócą. Ponieważ Promise.all sama zwraca obietnicę, funkcja zewnętrzna nie musi być async.

const someFunction = (myArray) => {
    const promises = myArray.map(async (myValue) => {
        return {
            id: "my_id",
            myValue: await service.getByValue(myValue)
        }
    });
    return Promise.all(promises);
}
 102
Author: lonesomeday,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-01 13:13:04

Jeśli chcesz uruchomić mapę z funkcją mapowania asynchronicznego, możesz użyć następującego kodu:

const resultArray = await Promise.all(inputArray.map(async (i) => someAsyncFunction(i)));

Jak to działa:

  • inputArray.map(async ...) zwraca tablicę obietnic-po jednej dla każdej wartości w inputArray.
  • umieszczenie Promise.all() wokół tablicy obietnic przekształca ją w jedną obietnicę.
  • pojedyncza obietnica z Promise.all() zwraca tablicę wartości - każda pojedyncza obietnica składa się z jednej wartości.
  • stawiamy await przed Promise.all() więc że czekamy na połączoną obietnicę, aby rozwiązać i zapisać tablicę rozdzielonych sub-obietnic do zmiennej resultArray.

Na końcu otrzymujemy jedną wartość wyjściową w resultArray dla każdego elementu w inputArray, odwzorowanego za pomocą funkcji someAsyncFunction. Musimy poczekać, aż wszystkie funkcje asynchroniczne zostaną rozwiązane, zanim wynik będzie dostępny.

 13
Author: MattCochrane,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-10-08 04:56:48

Dzieje się tak dlatego, że funkcja w map nie jest asynchroniczna , więc nie możesz oczekiwać w instrukcji return. Kompiluje się z tą modyfikacją:

const someFunction = async (myArray) => {
    return myArray.map(async (myValue) => { // <-- note the `async` on this line
        return {
            id: "my_id",
            myValue: await service.getByValue(myValue)
        }
    });
};

Wypróbuj w Babel REPL

Więc ... nie jest możliwe, aby dać rekomendację bez oglądania reszty aplikacji, ale w zależności od tego, co próbujesz zrobić, albo zrobić funkcję inner asynchroniczną lub spróbować wymyślić jakąś inną architekturę dla tego bloku.

Update: we może się kiedyś uda: https://github.com/MylesBorins/proposal-top-level-await

 10
Author: helb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-10 10:34:05