Bitte berücksichtigen Sie, dass ähnliche Fragen zu SO gestellt wurden und ich die meisten davon durchgesehen habe.

Ich mache einen RESTful-Service, der die Datenbank abfragen muss, um die Daten zu erhalten. Ich habe den Code geschrieben, der die Datenbank korrekt abfragt, aber immer undefiniert zurückgibt. Der Code ist hier:

function returnAll(){
    ModuleDBService.find({},function(err,data){
        if(err){
            console.log('Error occured while retrieving the documents!');
        }
        return data;
    });
}

Ich habe das Modul exportiert mit:

module.exports = {
    getAll:returnAll
};

Nachdem ich so viel gegraben hatte, stellte ich fest, dass ich einen Rückruf verwenden muss, um die Daten zu erhalten. Ich habe viele Beispiele durchgesehen und versucht, eine ähnliche Technik auf meinen Code anzuwenden. Der geänderte Code sah folgendermaßen aus:

function getAllFromDatabase(callback){
    ModuleDBService.find({},function(err,data){
        if(err){
            console.log('Error occured while retrieving the documents!');
        }
        callback(returnAll(data));
    });
}


function returnAll(data){ return data;}

Und dann auf ähnliche Weise wie oben zurückgeben.

Aber jetzt erhalte ich die Fehlermeldung, dass ModuleDAO.getAll keine Funktion ist (ich verwende var ModuleDAO = require ('Pfad zum Datenbankdienst').

Ich habe viele Variationen des Codes ausprobiert, ein paar Videos auf YouTube durchgesehen, die entweder zu einer undefinierten Rückkehr oder zu dem oben angegebenen Fehler geführt haben. Wenn jemand den Code reparieren und Licht in diese ganze Rückrufsache bringen könnte (oder eine solide Dokumentation liefern könnte, um sie zu verstehen), wäre dies eine große Hilfe.

Vielen Dank.

BEARBEITEN: Nach all den äußerst hilfreichen Antworten finden Sie hier eine Zusammenfassung:

Rückrufe können keine Daten zurückgeben. Übergeben Sie die Funktion (die Rückruffunktion), die Ihr Programm mit den Daten aufrufen soll. In meinem Fall war es mein Router, der die Daten zurückgab.

Hier ist der korrigierte Code:

function returnAll(callback) {
    ModuleDBService.find({}, function (err, data) {
        if (err) {
            console.log("Error while retrieving the document!")
            callback(null);
        }
        callback(data);
    });
}

Ich habe diesen Code in meinem Router verwendet als:

mainAPIRouter.post('/api/module', function (req, res) {
    try {
        moduleDAO.getAll(function(data){
            res.status(200);
            res.json(data);
        });
    } catch (error) {
        res.status(500);
        return res.send("Invalid request");
    }
});

Vielen Dank an alle, die geholfen haben! :) :)

1
metamemelord 18 Apr. 2018 im 23:45

3 Antworten

Beste Antwort

Du bist nah dran. Sie benötigen die Funktion returnAll() nicht und müssen getAllFromDatabase exportieren und eine callback übergeben:

function getAllFromDatabase(callback){
    ModuleDBService.find({},function(err,data){
        if(err) {
            console.log('Error occured while retrieving the documents!');
        }
        callback(data);
    });
}

module.exports = {
    getAllFromDatabase: getAllFromDatabase
};

Wenn Sie es dann verwenden möchten, benötigen Sie eine Rückruffunktion :

dataModule.getAllFromDatabase(callbackHandler);

function callbackHandler(dataFromDatabase) {
    // this function will be executed when ModuleDBService executes the callback
    console.log(dataFromDatabase);
}

Ein kleines Detail: Wenn err Truthy ist, sollten Sie den Rückruf nicht ausführen:

if(err) {
    console.log('Error occured while retrieving the documents!');
} else {
    callback(data);
}
1
raul.vila 18 Apr. 2018 im 20:51

Wie bereits erwähnt, können Sie einen Rückruf verwenden. Sie können auch ein Versprechen verwenden, wenn Sie es vorziehen:

function returnAll(){
    return new Promise(function(resolve, reject) {
    ModuleDBService.find({},function(err,data){
        if(err){
            console.log('Error occured while retrieving the documents!');
                reject(err);
        }
          resolve(data);
    });
     });
}

Sie würden dann so etwas verwenden, um darauf zuzugreifen:

returnAll()
  .then(data=> {console.log(data); })
  .catch(err=> { console.log(err); });

* Bearbeiten: Da Sie einen Rückruf verwenden möchten, dachte ich, ich würde dort auch meine $ 0,02 hinzufügen. Der rationalste Ansatz wäre, nur den Rückruf zu verwenden, den Sie mit ModuleDBService.find ohne die Ad-hoc-Funktion übergeben. Es ist jedoch gut zu überprüfen, ob der Rückruf tatsächlich eine Funktion ist, und wenn dies nicht der Fall ist, wird Ihr Code fehlertoleranter.

function returnAll(cb){
    if(typeof cb!=='function') cb = function() {};
    ModuleDBService.find({},cb);
}
1
David784 18 Apr. 2018 im 21:10

Sie möchten einfach callback() mit den Daten aufrufen, die Sie als Argument benötigen. Sie machen die Sache viel komplizierter, indem Sie eine andere Funktion an den Rückruf übergeben. Versuchen Sie etwas wie:

function returnAll(callback) {
  ModuleDBService.find({}, function(err, data) {
    if (err) return callback(err)
    callback(null, data);
  });
}

returnAll(function(err, data)) {
// it's customary for callbacks to take an error as their first argument
  if (err) {
    console.log('Error occured while retrieving the documents!');
  } else {
    // use data here!!
  }
}
1
Mark Meyer 18 Apr. 2018 im 20:52