PROBLEMA Node JS - Funzioni asincrone e ciclo for

Baio84

Nuovo Utente
31
0
CPU
Intel Pentium 4
Scheda Madre
ASUS Oxford
HDD
150 GB
RAM
DDR 1,50 GB
GPU
GeForce 6200
Monitor
Benq T720
OS
Windows 7 Ultimate 32 bit SP1
Buongiorno,
spiego la mia situazione. Devo reperire dei dati che devo inserire in un DB. Dopodichè i dati appena inseriti li devo elaborare.

Codice:
estrarreInfo()
.then(info => {
    ...
    return info;
})
.then(info2 => {
    var nrDati = info2.length;
    var player = '';
    for(var x = 0; x < nrDati; x++) {
        player = info2[x];
        inserireDati(player)
        .then(() => {
            aggiornareDati(player);
        })
        .catch(err => console.log(err));
    };
})
.catch(err => console.log(err));

Nel primo then estraggo le informazioni che mi servono e le ritorno sottoforma di object. Nel secondo then comincio a lavorare sul DB. Col ciclo for lavoro per ogni elemento di info2. La funzione asincrona inserireDati mi inserisce correttamente ogni elemento dell'object. Il problema si presenta con la funzione asincrona aggiornareDati. In questo caso mi aggiorna, per tutti gli elementi, solo l'ultimo elemento, come se la variabile x del ciclo for fosse già all'ultimo elemento a partire già dal primo.

Non ho molta dimestichezza con sincrono e asincrono, però intuisco che, essendo il ciclo for sincrono, viene elaborato prima dell'asincrono e questo dà un risultato diverso da quello aspettato. Il problema è che, non avendo appunto delle basi sull'asincrono, non so come risolvere questo nodo. E' necessario un ciclo for in modalità asincrona?
 

Mursey

Super Moderatore
Staff Forum
Utente Èlite
8,243
5,674
Per prima cosa puoi fare un solo then all'inizio, anche perchè fatto così sarebbe sbagliato visto che la prima funzione tornerebbe info invece di una Promise.
JavaScript:
estrarreInfo().then(info => {
    var player = '';
    for(var x = 0; x < info.length; x++) {
        player = info[x];
        inserireDati(player).then(() => {
            aggiornareDati(player);
        })
        .catch(err => console.log(err));
    };
}).catch(err => console.log(err));
Detto questo cosa fa inserireDati?
Perchè prende in ingresso player ma non torna nulla nella funzione che hai messo nel then...

Aggiungo un esempio di uso corretto di una Promise:
JavaScript:
// dichiarazione
function estrarreInfo() {
    return new Promise((resolve, reject) => {
      // operazioni asincrone per estrarre info
         // quando pronte si chiama resolve(info);
         // in caso di problemi o errori si usa reject();
   });
}

// chiamata
estrarreInfo().then(function(info) {
   // usi info
});
 
Ultima modifica:

Baio84

Nuovo Utente
31
0
CPU
Intel Pentium 4
Scheda Madre
ASUS Oxford
HDD
150 GB
RAM
DDR 1,50 GB
GPU
GeForce 6200
Monitor
Benq T720
OS
Windows 7 Ultimate 32 bit SP1
Mi scuso. Per il primo then sono stato fuorviante perchè all'interno elaboro i dati info in un object creato ad hoc e ritorno quello.
Era meglio scrivessi così:
Codice:
estrarreInfo()
.then(info => {
    /* elaboro i dati presi da info e creo l'object */
    return objectCreato;
})
// resto del codice

inserireDati è creata come funzione async/await. Il parametro player lo utilizzo per ricercarlo nel database. Se è presente faccio un primo aggiornamento. Se non è presente lo inserisco. Non ritorno nulla però.

Anche la funzione aggiornareDati è in formato async/await. Ricerca player nel database per estrapolare dei dati, li rielaboro e poi li aggiorno.

Intanto che scrivo sto pensando di unirle sotto un'unica funzione. L'unico problema è capire se possa funzionare con il modulo che sto utilizzando per gestire il database. Per informazione sto usando nedb-promises.js
 

Mursey

Super Moderatore
Staff Forum
Utente Èlite
8,243
5,674
inserireDati è creata come funzione async/await. Il parametro player lo utilizzo per ricercarlo nel database. Se è presente faccio un primo aggiornamento. Se non è presente lo inserisco. Non ritorno nulla però.
La funzione deve ritornare una Promise altrimenti come fai a fare il then() ?
Mi sa che devi ancora studiare bene le funzioni asincrone... ?

Se entri meglio nel dettaglio posso aiutarti io, intanto butta giù qualcosa.
 

Baio84

Nuovo Utente
31
0
CPU
Intel Pentium 4
Scheda Madre
ASUS Oxford
HDD
150 GB
RAM
DDR 1,50 GB
GPU
GeForce 6200
Monitor
Benq T720
OS
Windows 7 Ultimate 32 bit SP1
Eh sì, devo ancora entrare nell'ottica giusta! Con PHP andavo di sincrono e mi bastava mettere giù righe passo a passo.

Io pensavo che, oltre che per sviluppare una promise, il then() potesse essere usato anche come "callback". Cioè una volta sviluppato il codice nel primo then(), puoi passare al codice nel then() seguente, senza dover passare per forza una nuova promise o ritornare qualche altro tipo di dato. Ma se mi dici che deve ritornare per forza qualcosa, questo mi servirà in futuro.

Comunque ho risolto inserendo tutto in un unica funzione asincrona async/await, con cui ora capisco perchè è di così facile lettura. Quindi ricerco il dato nel database, se lo trova lo aggiorna, se non c'è lo inserisco. Richiamo ancora lo stesso dato nel database. Estrapolo i dati che mi servono, li elaboro e li riaggiorno.

Passando ad async/await ho risolto ma ora ti posto il codice precedente a cui ero arrivato ma che mi dava problemi di lettura del DB.

Codice:
estrarreInfo()
.then(info => {
    /* elaboro i dati e ritorno un object */
    return objectCreato;
})
.then(info2 => {
    var nrDati = info2.length;
    var player = '';
    for(var x = 0; x < nrDati; x++) {
        player = info2[x];
        inserireDati(player)
    };
    aggiornareDati();
})
.catch(err => console.log(err));

Inizialmente l'idea era questa. inserireDati() inseriva uno ad uno i valori tramite il ciclo for. Finito il ciclo utilizzavo aggiornareDati() per aggiornare in blocco tutti i valori, richiamandoli dal DB appena aggiornato e utilizzando al suo interno il ciclo for. Qui però il problema che avevo, era che quando richiamavo i dati in aggiornareDati() dal DB appena aggiornato, i dati non venivano letti, anche se il DB veniva popolato.
Esempio esplicativo: DB vuoto, inserireDati() popola il DB, aggiornareDati() non legge i dati appena inseriti ma legge il database come vuoto, anche se alla fine del codice il DB risulta popolato.
 

Mursey

Super Moderatore
Staff Forum
Utente Èlite
8,243
5,674
Io pensavo che, oltre che per sviluppare una promise, il then() potesse essere usato anche come "callback". Cioè una volta sviluppato il codice nel primo then(), puoi passare al codice nel then() seguente, senza dover passare per forza una nuova promise o ritornare qualche altro tipo di dato. Ma se mi dici che deve ritornare per forza qualcosa, questo mi servirà in futuro.
Vedila così:

Funzione A torna una Promise
La Promise è un oggetto che espone il metodo then()​
Chiami la funzione A()
Scrivere A().then() vuol dire che chiami la then dell'oggetto ritornato da A​
Puoi fare una catena di then() a patto che ogni chiamata ritorni un oggetto Promise

Quando la Promise viene risolta, la sua then() è eseguita.
 

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!