• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Asynchroniczność w js

0 głosów
1,193 wizyt
pytanie zadane 25 kwietnia 2018 w JavaScript przez pclolowicz Użytkownik (500 p.)

Cześć, 

próbuję napisać metodę która zwróci mi wyniki kilku zapytań w postaci tablicy. Problem polega na tym, że całość metody zdąży się wykonać zanim przyjdą odpowiedzi i zostaną zapisane do tablicy w związku z czym funkcja zwraca pustą tablicę. Proszę o pomoc 

 

 function getData(_userIDs, _type, _pattern) {
    return new Promise( async function (resolve, reject)
    {
        var tab = [];
        const oauth =
            {
                consumer_key: 'ypvKtBzSXFcKsu37MhWt',
                consumer_secret: 'ZD343443434334ftuXMzEV',
                token: 'R643434434kG4fKVRr',
                token_secret: 'Xx433434343434LXauKHCdBY563zzLq'
            }
            , url = 'https://dffdfdfdfdfdfdfdfd';

        for (var i = 0; i < Object.keys(_userIDs.items).length; i++) {
            const qs = {
                user_id: _userIDs.items[i].user.id,
                fields: _pattern
            }

           const x=  await request.get({ url: url, oauth: oauth, qs: qs, json: true }, function (e, r, user) {
                if (e) {
                    console.log("Blad!");
                    return;
                }
                
                else {
                    tab.push(user);
                    // console.log(user);
                    console.log("Iteracja : " + i);            
                }

            });
         
        }
        resolve(tab);
    });
    
}

 

2 odpowiedzi

+3 głosów
odpowiedź 25 kwietnia 2018 przez adrian17 Mentor (354,880 p.)
wybrane 25 kwietnia 2018 przez pclolowicz
 
Najlepsza

Ciężko stąd wyczytać, co dokładnie ma robić kod, ale będę zgadywał. Zgaduję, że `_userIDs.items` jest tablicą (jeśli nie, to dość łatwo można poprawić moje przykłady)

Ogólnie dość mocno tu pomieszałeś rzeczy. Jeśli używasz Promise, to dość dziwne jest, że funkcja w środku też jest asynchroniczna. Dziwne też, że `request.get` używasz z await, ale też przekazujesz mu callbacka - zazwyczaj robi się albo jedno, albo drugie. Skoro mówisz, że funkcja się kończy zbyt szybko, to zgaduję, że `request.get` jest callbackowe.

W każdym razie, skoro chcesz zrobić kilka zapytań, a getData ma zwrócić Promise z tablicą z pobranymi danymi, dobrymi narzędziami będą prawdopodobnie .map() (żeby zamienić listę userów na zapytania) i Promise.all (które zaczeka aż wszystkie zapytania się zakończą i spakuje wynik w listę).

Zrobiłbym to tak (na sucho, więc możliwe że z błędami). Jeśli `request.get` zwraca promise:

function getData(_userIDs, _type, _pattern) {
    const oauth = "...";
    const url = "...";

    const promises = _userIDs.items.map(item => {
        const qs = {
            user_id: item.user.id,
            fields: _pattern
        };

        return request.get("...");
    });

    return Promise.all(promises);
}

A jeśli jest callbackowe, to jest trochę trudniej, bo trzeba opakować callback w promise. Można by też dla porządku wrzucić to w osobną funkcje, ale tu tego nie zrobiłem:

function getData(_userIDs, _type, _pattern) {
    const oauth = "...";
    const url = "...";

    const promises = _userIDs.items.map(item => {
        const qs = {
            user_id: item.user.id,
            fields: _pattern
        };

        return new Promise((resolve, reject) => {
            request.get("...", (e, r, user) => {
                if (e) {
                    reject("...");
                    return;
                }
                resolve(user);
            });
        });
    });

    return Promise.all(promises);
}

 

1
komentarz 25 kwietnia 2018 przez pclolowicz Użytkownik (500 p.)
edycja 25 kwietnia 2018 przez pclolowicz

Dziękuję za bardzo wyczerpującą i pouczającą odpowiedź ! Udało mi się osiągnąć to co chciałem. Poniżej umieszczam kod który poprawiłem.

function getData(_userIDs, _type, _pattern) {
        const oauth =
            {
                consumer_key: 'ypvdsKsu37MhWt',
                consumer_secret: 'ds',
                token: '3KndsAcEwh8Yt',
                token_secret: 'DYfc3dsJT6FPsUrTbvFd'
            }
          , url = 'https://sddsdsdser';

      const promises = _userIDs.items.map(item => {
          const qs = {
              user_id: item.user.id,
              fields: _pattern
          }
          return new Promise((resolve, reject) => {
              request.get({ url: url, oauth: oauth, qs: qs, json: true }, (e, r, user) => {
                  if (e) {
                      reject("...");
                      return;
                  }
                  resolve(user);
              });
          });
    });

      return Promise.all(promises);
}

 

+2 głosów
odpowiedź 25 kwietnia 2018 przez Jacek Rojek Bywalec (2,380 p.)
edycja 26 kwietnia 2018 przez Jacek Rojek

Asynchroniczny kod w Js mozesz pisac na wiele sposobow:

1 Callbacks 

request.get({  }, function (e, r, user) {

// callback function here

})

2. Promise

var getData = new Promise(function(resolve, reject) {
  setTimeout(resolve, 100, 'foo');
});

getData.then(e =>console.log(e))

3. Async/Await 

async function getData() {
  var result = await request.get();
  return result
}

getData();

W twoim przypadku probujesz uzyc wszystkich tych metod jednoczesnie.

Najpierw zdecyduj ktorego z rozwiazan uzyjesz i nie mieszaj go z innymi.

Na przyklad

const getData = async (users: Array<User>) => Promise.all(users.map(request.get))

getData().then(usersData => console.log(usersData))

Edit: dodanie Promise.all,  uproszczenie map()

2
komentarz 25 kwietnia 2018 przez adrian17 Mentor (354,880 p.)
getData().then

(to nie zadziała, bo Twój map() zwrócił tablice promise'ów. Potrzebujesz Promise.all. Poza tym, `async user => await request.get(user)` można bezpośrednio zastąpić przez samo request.get(user) - które zwróci promise robiący to samo)

Podobne pytania

0 głosów
1 odpowiedź 222 wizyt
pytanie zadane 15 stycznia 2019 w JavaScript przez CP733 Początkujący (390 p.)
0 głosów
0 odpowiedzi 591 wizyt
0 głosów
0 odpowiedzi 509 wizyt
pytanie zadane 9 lipca 2020 w JavaScript przez Hardwell Dyskutant (9,060 p.)

93,631 zapytań

142,553 odpowiedzi

323,056 komentarzy

63,139 pasjonatów

Advent of Code 2025

Top 15 użytkowników

  1. 2900p. - dia-Chann
  2. 2870p. - DziarnowskiJ
  3. 2827p. - Łukasz Piwowar
  4. 2783p. - raydeal
  5. 2758p. - Adrian Wieprzkowicz
  6. 2713p. - rucin93
  7. 2579p. - Łukasz Eckert
  8. 2459p. - CC PL
  9. 2184p. - Maurycy W
  10. 2082p. - Michal Drewniak
  11. 1885p. - robwarsz
  12. 1811p. - rafalszastok
  13. 1600p. - Rafał Trójniak
  14. 1588p. - Tomasz Bielak
  15. 1494p. - ssynowiec
Szczegóły i pełne wyniki

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Kursy INF.02 i INF.03
...