Reputation: 4269
How do you run through multiple functions in nodejs / expressjs? In php it's straightforward, call one function after the other but this callback business in node is confusing, I keep getting errors that a variable isn't defined and such. Here is the basic idea of what I'm doing.
var express = require('express');
var request = require('request');
var app = express();
app.get('/user/:id', function(req, res) {
var id = req.params.id;
getInformation(id, function(info) {
res.send(info);
});
});
app.listen(3000);
getInformation(id, callback) {
var qty = makeExternalApiCall();
var color = secondFunction(id);
callback({quantity: qty, color: color});
}
makeExternalApiCall() {
request({uri: 'https://provider.com/api/stuff/'}, function(error, response, body) {
if (!error && response.statusCode == 200) {
return body.qty;
}
}
}
secondFunction(id) {
//look up color by id
var color = "blue";
return color;
}
Upvotes: 2
Views: 5745
Reputation: 32
You can also use next() function, this gives you modularity within a route file or among routes files.
Even you needn't worry about async and sync environments.
Do next() from within callback it will execute only after that callback is done or condition fulfilled when that callback is executed.
https://expressjs.com/en/guide/using-middleware.html
Upvotes: 0
Reputation: 91799
Running through multiple functions is similar to as it would be in PHP, unless it involves asynchronous functions. An asynchronous callback is a function that can be called at any time, and will not work with the return
keyword. Take this callback for example:
var cb = function(arg) {
console.log(arg);
};
We can pass this callback function into another function, and have that function call cb()
from within:
function call(text, callback) {
callback(text);
};
var txt = 'a string';
call(txt, cb);
console.log('breakpoint');
The example above runs synchronously. Therefore the order of execution is:
call() -> cb()
console.log()
But if we delay the function or add a timer (process.nextTick
waits until the callstack of functions is empty, then executes what has been queued):
function call(text, callback) {
process.nextTick(function() {
callback(text);
});
};
And run it again, we get a different execution order because cb()
was queued to run after the callstack is empty (right after console.log()
runs, it's empty):
call()
console.log()
-> cb()
Most undefined variable errors are caused by accessing a variable before it's set. For example, take the asynchronous function foo()
.
var data;
foo(function(bar) {
data = bar;
});
console.log(data);
The callback function(bar) { ... });
may have been called after the console.log()
, which means console.log()
runs before data
is given a value.
As for your specific problem, the request module is asynchronous and uses a callback, so you can't use a return value from within the HTTP request. To get a resultant value from within a callback function, you need to pass it to another callback. Using the return
keyword will just stop the function's execution. So change this:
var options = {
uri: 'https://provider.com/api/stuff/'
};
function makeExternalApiCall() {
request(options, function(err, res, body) {
if (!err && res.statusCode == 200) {
return body.qty;
}
}
};
To use a callback:
function makeExternalApiCall(callback) {
request(options, function(err, res, body) {
if (!err && res.statusCode == 200) {
callback(null, body.qty);
}
}
};
The function would then be used like so:
makeExternalApiCall(function(err, qty) {
// here is qty
});
So your routing code might look like this, using nested callbacks:
function getInformation(id, callback) {
var color = secondFunction(id);
makeExternalApiCall(function(err, qty) {
callback({ quantity: qty, color: color });
});
};
app.get('/user/:id', function(req, res) {
var id = req.params.id;
getInformation(id, function(info) {
res.send(info);
});
});
Upvotes: 4