javascript - Få funksjonskall til å vente på web SQL-spørring


Primecheck-funksjonen skal returnere sann eller falsk avhengig av om det angitte tallet er primtall eller ikke. Hvis tallet er et primtall, legger funksjonen det til i PRIMES-tabellen. Dette er en Sieve of Eratosthenes-algoritme, men den er ikke ferdig ennå.

function primecheck (number) {
    var isprime = true;
        if (number%10 == 1 || number%10 == 3 || number%10 == 7 || number%10 == 9) {
        db.transaction(function (tx) {
            tx.executeSql('SELECT * from Primes', [], function (tx, result) {
                for (var i = 1; i < result.rows.length; i++) {
                    if (number%result.rows.item(i)['prime'] == 0) {
                        isprime = false;
                        break;
                    }
                }
                if (isprime) {
                    tx.executeSql('INSERT INTO PRIMES (prime) values (?)', [number]);
                }
                return isprime;
            }, null);
        }, null, null);

    }
    else {
        isprime = false;
        return isprime;
    }
}

Problem: når jeg sender tall som ikke slutter på 1, 3, 7, 9, returnerer funksjonen true, det er greit. Men når jeg sender andre tall, returnerer funksjonen undefined. Jeg antar det er fordi funksjonskallet ikke "venter" på at SQL-spørringen skal fullføres, så jeg må bruke en slags callback-funksjon. Men det fungerte ikke.

Svar #1

Hvis funksjonen din utfører asynkrone operasjoner, kan den ikke returnere en verdi basert på resultatet av disse asynkrone operasjonene. (Dette er fordi de asynkrone funksjonene ikke vil kjøre før den nåværende utførelsen er ferdig, på grunn av JavaScripts enkelttrådede natur.) I stedet bør funksjonen din forvente en callback-funksjon som tar den verdien som ellers ville blitt returnert som et argument.

Du kaller for øyeblikket funksjonen din slik:

var isprime = primecheck(someNum);
// now do something with isprime

Men du må bruke en tilbakekalling:

primecheck(someNum, function(isprime) {
    // now do something with isprime
});

Bare legg til et andre tilbakeringingsargument, og kall på den tilbakeringen i stedet for å bruke en return:

function primecheck (number, callback) {
    var isprime = true;
        if (number%10 == 1 || number%10 == 3 || number%10 == 7 || number%10 == 9) {
        db.transaction(function (tx) {
            tx.executeSql('SELECT * from Primes', [], function (tx, result) {
                //....
                callback(isprime);
            }, null);
        }, null, null);
    }
    else {
        isprime = false;
        callback(isprime);
    }
}

Nå returnerer primecheck ingenting, men callback-funksjonen du sender inn i primecheck vil bli kalt med isprime som sitt første argument hver gang primecheck bestemmer primtallstatusen til inputen.