Come posso attendere il completamento di una promessa prima di restituire la variabile di una funzione?


149

Sto ancora lottando con le promesse, ma sto facendo progressi grazie alla comunità qui.

Ho una semplice funzione JS che interroga un database Parse. Dovrebbe restituire la matrice dei risultati, ma ovviamente a causa della natura asincrona della query (da qui le promesse), la funzione ritorna prima dei risultati, lasciandomi con una matrice indefinita.

Cosa devo fare per far aspettare questa funzione per il risultato della promessa?

Ecco il mio codice:

function resultsByName(name)
{   
    var Card = Parse.Object.extend("Card");
    var query = new Parse.Query(Card);
    query.equalTo("name", name.toString());

    var resultsArray = [];

    var promise = query.find({
               success: function(results) {
               // results is an array of Parse.Object.
                             console.log(results);
                             //resultsArray = results;
                             return results;
               },

               error: function(error) {
               // error is an instance of Parse.Error.
                             console.log("Error");
               }
    });                           

}

3
Puoi anche prendere in considerazione l'utilizzo di asincrono / await. Il nodo ora supporta asincrono / attendi fuori dalla scatola dalla versione 7.6
Viliam Simko,

Risposte:


66

Invece di restituire un, resultsArraysi restituisce una promessa per un array di risultati e poi thenquello sul sito di chiamata - questo ha l'ulteriore vantaggio del chiamante che sa che la funzione sta eseguendo I / O asincroni. La concorrenza del codice in JavaScript si basa su questo: potresti voler leggere questa domanda per avere un'idea più ampia:

function resultsByName(name)
{   
    var Card = Parse.Object.extend("Card");
    var query = new Parse.Query(Card);
    query.equalTo("name", name.toString());

    var resultsArray = [];

    return query.find({});                           

}

// later
resultsByName("Some Name").then(function(results){
    // access results here by chaining to the returned promise
});

Puoi vedere altri esempi sull'uso delle promesse di analisi con le query nel post sul blog di Parse al riguardo .


puoi dirmi qual è il supporto di questo? IE9 supporta questo?
sandrina-p,

Sì, ma Parse è per lo più morto, quindi c'è @SandrinaPereira. Questo è il codice cloud di analisi .
Benjamin Gruenbaum,

1
Ah, quindi questo non è solo javascript puro? Stavo cercando un modo per farlo (
attendo che

La domanda riguarda il codice di analisi, non le promesse. Le promesse possono funzionare (con una libreria) in qualsiasi browser. Bluebird funziona su IE6 e netscape 7.
Benjamin Gruenbaum,

1
Sto leggendo SO da due giorni ormai, e ancora nessuno lo ha risolto. Questa risposta accettata è la stessa di ogni altra. La funzione restituisce una promessa, non un valore come richiesto dall'OP. Perché questa risposta è contrassegnata come accettata?
iGanja,

19

Cosa devo fare per far aspettare questa funzione per il risultato della promessa?

Usa async/await(NON parte di ECMA6, ma disponibile per Chrome, Edge, Firefox e Safari dalla fine del 2017, vedi canIuse )
MDN

    async function waitForPromise() {
        // let result = await any Promise, like:
        let result = await Promise.resolve('this is a sample promise');
    }

Aggiunto a causa di un commento: una funzione asincrona restituisce sempre una Promessa e in TypeScript sarebbe simile a:

    async function waitForPromise(): Promise<string> {
        // let result = await any Promise, like:
        let result = await Promise.resolve('this is a sample promise');
    }

4
La funzione asincrona restituirà comunque un oggetto promessa se chiamata senza un wait (o in codice non asincrono). Controlla il risultato di console.log (waitForPromise ()) se non sei sicuro. Un controllo di console.log (risultato) all'interno della funzione asincrona sarà stampare ciò che vi aspettate, ma il ritorno dalla funzione asincrona avviene immediatamente senza bloccare e ritorna una promessa. Il blocco in javascript di solito è molto male poiché è una singola applicazione thread e il blocco farà morire di fame qualsiasi altro client pub / sub di notifiche che essenzialmente mette in ginocchio l'intera app.
SRM,

1
.net ha .wait () sulla "promessa" come la classe di attività. Javascript non ha questa funzione? Devo aspettare qualcosa prima di uscire dal mio strumento da riga di comando del nodo che potrebbe reindirizzare il suo output a un altro strumento. "await" funziona solo all'interno delle funzioni asincrone. Significa che non funziona al di fuori dell'ambito di una promessa.
TamusJRoyce,

@SRM Sento che il tuo commento si basa su un'interpretazione errata del campione - si tratta del Promise.resolve "interno" (come l'esempio più semplice di Promessa), quindi non c'è nessun chiamante esterno come stai affermando nel tuo commento. Quindi ho deciso di aggiornare la risposta.
Martin Meeser,

@TamusJRoyce Indovina che è una domanda a sé stante, ma penso che in C # puoi usare Task.ContinueWith (Task), che è la stessa idea che vedi nella risposta accettata (dove si chiama "then ()").
Martin Meeser,

Penso di vedere ora. Posso praticamente avvolgere il mio intero script in un'unica enorme funzione asincrona. E chiama quella funzione come ultima riga della mia sceneggiatura. Quella funzione sarebbe ancora un po 'di piastra della caldaia. Ma molto meno di quanto precedentemente percepivo. Non sono abituato a scrivere funzioni all'interno di funzioni. Grazie @MartinMeeser!
TamusJRoyce,

3

Non si desidera far attendere la funzione, poiché JavaScript deve essere non bloccante. Piuttosto restituire la promessa alla fine della funzione, quindi la funzione chiamante può utilizzare la promessa per ottenere la risposta del server.

var promise = query.find(); 
return promise; 

//Or return query.find(); 

1
L'intera cosa di callback con il success:bit è disattivata.
Benjamin Gruenbaum,

O meglio: return query.find();.
schiaccia il

Ok Lo lascerò così a scopo illustrativo, ma lo aggiungerò come commento.
Traccia il

Ho provato questo, ma i risultati sembrano essere indefiniti. resultsByName ("nome"). then (funzione (risultati) {console.log ("got array" + results.count);});
mac_55,

1
Grazie, ci deve essere stata una sorta di errore nella funzione dei risultati. Sta lavorando adesso. Ho cambiato il mio console.log in results.length e posso vedere che c'è 1 voce nel mio array restituito :)
mac_55

2

In realtà non stai usando le promesse qui. Parse ti consente di utilizzare callback o promesse; la tua scelta.

Per utilizzare le promesse, procedi come segue:

query.find().then(function() {
    console.log("success!");
}, function() {
    console.log("error");
});

Ora, per eseguire cose dopo che la promessa è stata completata, puoi semplicemente eseguirla all'interno del callback promessa all'interno della then()chiamata. Finora questo sarebbe esattamente lo stesso dei callback regolari.

Fare davvero buon uso delle promesse è quando le incateni, in questo modo:

query.find().then(function() {
    console.log("success!");

    return new Parse.Query(Obj).get("sOmE_oBjEcT");
}, function() {
    console.log("error");
}).then(function() {
    console.log("success on second callback!");
}, function() {
    console.log("error on second callback");
});

Che tipo di oggetto è l'oggetto risultati? poiché non sembra contenere il mio array
mac_55,

Dovrebbe essere una matrice di Parse.Object's.
schiaccia il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.