Utilizzo di promesse, chiusure e ricorsioni in Node.js

3

Ho utilizzato una chiamata ricorsiva a una chiusura per attenuare alcune condizioni di gara che sto ottenendo (è quello che penso sia). Mi piacerebbe sapere se (e perché) questa è una buona soluzione o una cattiva soluzione.

function getResources(activity, resource) {
    var q = when.defer(),
    resourceQuery = constructSelectionQuery(resource),
    timeoutCounter = 0,
    timeoutLimit = 100;
    function queryDatabase() {
        query.getResult({
            query: resourceQuery
        }, function(err, result) {
            if (result.length === 0) {
                if (timeoutCounter > timeoutLimit) {
                    q.reject();
                }
                timeoutCounter++;

                //subsequent call(s)
                queryDatabase();
            } else {
                q.resolve(result);
            }
        });
    }

    //initial call
    queryDatabase();

    return q.promise;

    }

Quello che sto cercando di accertare è la validità dell'uso della ricorsione e della chiusura in questa combinazione - è questo un modo accettabile di affrontare il problema di ripetere la chiamata al database? Senza la ripetizione della chiamata il risultato è a volte vuoto. Questo è curioso dato che questa funzione viene chiamata solo dopo che il record è stato salvato. Tuttavia questo è in un altro sistema quindi suppongo che la velocità di indicizzazione sia errata in MySQL - Non voglio entrare in quell'aspetto del sistema perché sono soddisfatto di quello che ho - La mia domanda è isolata utilizzando questo modello - una chiamata ricorsiva alla chiusura come un modo per ripetere la chiamata.

    
posta Stevo 02.04.2014 - 14:57
fonte

1 risposta

1

Il nesting è un po 'difficile da leggere. Se lo scrivi come segue, è più facile capire cosa sta succedendo.

function queryDatabase() {
    query.getResult({query: resourceQuery}, queryDone);
}

function queryDone(err, result) {
    if (result.length !== 0) {
        q.resolve(result);
    }
    else if (timeoutCounter++ > timeoutLimit) {
        q.reject();
    }
    else {
        queryDatabase();
    }
}

Poiché query.getResult() è asincrono (presumo, altrimenti non avresti bisogno di una promessa), ciò significa che queryDatabase() tornerà prima che venga chiamato queryDone() . Quando queryDatabase() è chiamato all'interno di queryDone() , verrà restituito, provocando anche il ritorno di queryDone() , prima che venga richiamato di nuovo. Quindi, mentre è ricorsivo in senso semantico, le chiamate alla funzione non sono mai annidate. Quindi non dovresti avere problemi come tenere 100 copie di un oggetto risultato nella memoria in una volta.

Per quanto riguarda lo stile, non vedo come potrebbe essere espresso senza ricorsione senza aggiungere complessità. Se questo pattern viene ripetuto frequentemente nel tuo codice, potresti creare una soluzione più generale, usando qualcosa come:

var promise = 
  repeatQueryUntil(resourceQuery, function(err, result) {return result.length !== 0;})
    
risposta data 02.04.2014 - 19:34
fonte

Leggi altre domande sui tag