Ryan Ryan - 26 days ago 9
HTTP Question

Having issues responding to an HTTP request with the proper array. Possible way to send results from within function with expressjs?

Problem Summary: So I'm working on a program that has an SQL database on the backend and I'm using the npm SQLite3 module to talk to it. When I make my HTTP request to the server I was told in another post that I should do a

res.send
with the function inside it so after the function ran, it would return whatever came from the function. Easy enough right? But then I ran into an issue with an asynchronous function
.all
(API Doc here). Essentially what happens is that I call my database and it returns everything inside to an object inside database.all, but database.all is an asynchronous function that is void and can't return anything. I've got a callback that sends the object inside the callback, but I don't know what to do with it from there, or if I even need a callback.

So my question is: can I send an HTTP response from somewhere inside my
.all
function or callback, or does my function have to return the array to where it was called? Code below to show you what I mean.

Chain of events (Github repo for refrence):

I've set up an angular controller to send the following HTTP request when my page loads:

$http.get('/LoadWaitingList')
.then(function(response) {
// alert("HTTP request set, getting data");
console.log(response.data);
});


and when the server (server.js) receives it, I do this:

app.get('/LoadWaitingList', function (req, res) {
res.send(DatabaseFunction.loadWaitingList());
})


which runs the loadWaitingList() function in another file named test.js:

function loadWaitingList() {
var callbackFunction = function(err, response){
var returnRow = response;
return returnRow;
}
updateDB.Manager(callbackFunction);
}


which calls
updateDB.Manager
, AKA this guy:

Manager : function(callback){
var fs = require("fs");
var file = "./Source/Server/Data/DaycareDB.db";
var exists = fs.existsSync(file);
if (!exists) {
throw new Error("File not Found");
}
var sqlite3 = require("sqlite3").verbose();
var db = new sqlite3.Database(file);
db.all("SELECT * FROM WaitingList", function(err, row) {
if (err){
callback(err);
return;
}
// console.log(row[0].ChildName);
callback(null, row);
return;
});
},


So finally we can see, after
db.all
runs, the values I'm after after in
row
.
row
is passed into
db.all
as a parameter and returned as an array, I've tried declaring it outside the
db.all
and passing it in and then printing out the results, but due to
db.all
being asynchronous it always comes up empty because the function hasn't run yet.

When I run my callback and check the object (using vscode debugger) after the callback has been called,
returnRow
has the proper data in it from my database.

How do I send the data that gets put into
row
and eventually
returnRow
back as a response? Is it possible to do the initial function call when we get the HTTP request a different way and then do a
res.send
from the callback or something?

Answer

You need to look at your callbacks.

app.get('/LoadWaitingList', function (req, res) {
  DatabaseFunction.loadWaitingList(function(err,data){
    if(err) {
      // handle the error here
    }
    // send the data
    res.send(data);
  }
});

Now loadWaitingList() needs to take a standard error-first callback as a parameter. This callback is passed through to updateDB.Manager() where it will be executed.

function loadWaitingList(callback) {
  updateDB.Manager(callback);
}