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

Problem z funkcją asynchroniczną

0 głosów
183 wizyt
pytanie zadane 2 marca 2020 w JavaScript przez smokolisz Mądrala (6,340 p.)

Cześć, chce żeby mój kod zaczekał aż funkcja asynchroniczna się zakończy.

Mam taki kod:

var hash = "test";
database.readSpecificUser(systemsJSON.users[id].id, function (result) {
       hash = result.pin;
});
console.log(hash);
            
return hash;

funkcja database.readSpecificUser jest asynchroniczna. Drugi parametr tej funkcji to callback, który jest wykonywany po tej funkcji. Ten callback zwraca wynik z bazy danych sqlite. Program powinien zaczekać, aż wróci ten callback, nadpisać zmienną hash tą wartością która przyszła w callbacku i dopiero pójść dalej (return hash;).

readSpecificUser: function readSpecificUser(id, callback) {
        this.db.transaction(function (transaction) {
                //kod asynchroniczny...
                callback(result);
        }, _this.errorHandler, _this.nullHandler);

        return false;
},

Ten console.log wypisuje "test", czyli wypisało się zanim ta funkcja asynchroniczna zwróciła callback.

Wiem jak to zrobić używając promisów, async/await. Problem w tym, że w tym projekcie musze koniecznie wspierać bardzo stare przeglądarki, które tego nie obsługują. Ma ktoś jakiś pomysł jak to zrobić?

Myślałem jeszcze nad czymś takim:

var hash = "test";
database.readSpecificUser(systemsJSON.users[id].id, function (result) {
       hash = result.pin;
       return hash;
});
            

W tym przypadku ten return chyba zwraca wartość do funkcji anonimowej a nie tej nadrzędnej w której wykonuje się ten kod. Wie ktoś jak to zrobić?

1 odpowiedź

+1 głos
odpowiedź 2 marca 2020 przez ScriptyChris Mędrzec (190,190 p.)
wybrane 2 marca 2020 przez smokolisz
 
Najlepsza

Pokaż jeszcze gdzie (w czym) zawiera się kod z pierwszego i trzeciego bloczka (użycie zmiennej hash)?

Skoro próbujesz tam zwracać wartość zmiennej hash, obstawiam że jest to jakaś funkcja. Więc z grubsza:

function getHash(hashCallback) {
  database.readSpecificUser(systemsJSON.users[id].id, hashCallback);
}

getHash(function (result) {
    var hash = result.pin;
    console.log('hash:', hash);
});


Co robisz z parametrem transaction i skąd wziąłeś zmienną result?:

readSpecificUser: function readSpecificUser(id, callback) {
        this.db.transaction(function (transaction) { // co robisz z tym parametrem?
                //kod asynchroniczny...
                callback(result); // skąd ta zmienna się tu wzięła?
        }, _this.errorHandler, _this.nullHandler);
 
        return false;
},

 

komentarz 2 marca 2020 przez smokolisz Mądrala (6,340 p.)
edycja 2 marca 2020 przez smokolisz

@JSHolic,
Hej, dzięki za odpowiedź. Tak wygląda rozszerzony kod z 1 bloczka: https://pastebin.com/mMu1k5gW

Co do drugiego pytania w tamtym bloczku też obciąłem troche kodu bo chciałem żeby pytanie było czytelniejsze, tak to wygląda w całości: https://pastebin.com/HHTDdApQ

Zrobiłem tak jak zaproponowałeś, niestety hash który jest zwracany w tym return to nadal "test"
 

function (user) {
            var hash = "test";

            function getHash(hashCallback) {
              database.readSpecificUser(systemsJSON.users[id].id, hashCallback);
            }
             
            getHash(function (result) {
                hash = result.pin
                console.log('hash:', hash);
            });


            // database.readSpecificUser(systemsJSON.users[id].id, function (result) {
            //     hash = result.pin;
            // });
            console.log("HASH ODCZYTANY Z BAZY", hash);

            return hash;
 
}

Twój console.log ("hash: ", hash) zwraca prawidłową wartość, natomiast ten niżej już zwraca test :/

1
komentarz 2 marca 2020 przez ScriptyChris Mędrzec (190,190 p.)

Do czego potrzebny Ci ten return hash? Jak już zauważyłeś, to jest fragmentu kodu wykonanego asynchronicznie i nie ma możliwości zwrócenia z niego wartości do kodu wykonanego synchronicznie (zwłaszcza, że to nie jest składnia z użyciem Promisów, async/await).

Mając szerszy kontekst (kod z pierwszego linka), powiedz co dalej chcesz zrobić ze zmienną hash?

Możesz w wyższym scope trzymać funkcję, która będziesz procesować wartość z result.pin (Twój hash) otrzymaną z callbacka z bazy danych.

function processHash(hash) {
    console.log('hash:', hash);
    // dalsze procesowanie

    // pamiętaj, że użycie tutaj return z czymkolwiek nie zadziała, jeśli tej funkcji użyjesz jako callback do kodu asynchronicznego
}

app.crypto.login(user, null, urlAlgorithm, function (username, password, headers) {
            //nie związany z tą sprawą kod
        }, function (user, encrypted) {
            return null;
        }, function (user) {
            database.readSpecificUser(systemsJSON.users[id].id, function (result) {
              processHash(result.pin);
            }); 
        });
komentarz 2 marca 2020 przez smokolisz Mądrala (6,340 p.)

Hej, dzięki za starania. Problem rozwiązałem niezbyt elegancko, ale czasami czas jest cenniejszy niż dobry kod.

Przyniosłem tą funkcję asynchroniczną na górę:

database.readSpecificUser(systemsJSON.users[id].id, function (result) {
        var hash = result.pin;

        app.request.get(urlUsers, {}, function (data) {
            var userId = void 0;

            for (var i = 0; i < data.length; i++) {
                if (user == data[i].name) {
                    userId = data[i].id;
                    break;
                }
            }

            var urlAlgorithm = urlForAlgorithms(url, userId);
            app.crypto.login(user, null, urlAlgorithm, function (username, password, headers) {
                
            //...

            }, function (user, encrypted) {
                return null;
            }, function (user) {
                //var hash = "test";

                /*function getHash(hashCallback) {
                  database.readSpecificUser(systemsJSON.users[id].id, hashCallback);
                }
                
                getHash(function (result) {
                    hash = result.pin
                    console.log('hash:', hash);
                });*/

                return hash;
      
            });
        }, function (xhr, data) {
            app.preloader.hide();
            //request error
        }, "json");
  });

 

1
komentarz 2 marca 2020 przez ScriptyChris Mędrzec (190,190 p.)

Doprecyzuję jeszcze mój komentarz w kodzie (linia 5):

// pamiętaj, że użycie tutaj return z czymkolwiek nie zadziała, jeśli tej funkcji użyjesz jako callback do kodu asynchronicznego

Miałem na myśli, że nie będziesz mógł zwrócić wartości na zewnątrz kodu asynchronicznego. Możesz natomiast zrobić w ten sposób:

function processHash(hash) {
    console.log('hash:', hash);
    
    // dalsze procesowanie
   var processedHash = 'somehow processed hash...';
 
   return processedHash;
}

function doFurtherHashProcessing(initiallyProcessedHash) {
  return hash.toUpperCase(); // w tej lub innej funkcji możesz dalej procesować hasha, przykładowo
}

////
            database.readSpecificUser(systemsJSON.users[id].id, function (result) {
              var resultOfHashProcessing = processHash(result.pin);
              var resultOfSomethingElse = doFurtherHashProcessing(resultOfHashProcessing);

              // itd.
            });

 

Podobne pytania

+1 głos
1 odpowiedź 1,994 wizyt
+2 głosów
2 odpowiedzi 1,287 wizyt
+1 głos
1 odpowiedź 3,564 wizyt

93,424 zapytań

142,421 odpowiedzi

322,646 komentarzy

62,785 pasjonatów

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

VMware Cloud PRO - przenieś swoją infrastrukturę IT do chmury
...