I've currently got a expressJS app and I'm trying to retrieve information from an API using the getStats
function. However, the profile
route I've written seems to be multiple nested callbacks. How would I prevent this? Is there a way to make it get all of the stats, then assign them to variables after they all of the stats are retrieved?
function getStats(access_token, time_range, x, callback) {
var stats = [];
var options = {
url: 'www.example',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
json: true
}
request(options, function(error, response, body) {
if (!error && response.statusCode == 200) {
for (i = 0; i < body.items.length; i++) {
stats.push(body.items[i].name);
}
return callback(stats);
}
})
}
app.get('/profile', function(req, res) {
var access_token = 1234;
getStats(access_token, 's', 'x', function(a){
console.log(a);
getStats(access_token, 's', 'y', function(b){
console.log(b);
getStats(access_token, 'm', 'x', function(c){
console.log(c);
getStats(access_token, 'm', 'y', function(d){
console.log(d);
getStats(access_token, 'l', 'x', function(e){
console.log(e);
getStats(access_token, 'l', 'y', function(f){
console.log(f);
res.send(a + "\n" + b + "\n" + c + "\n" + d + "\n" + e + "\n" + f);
});
});
});
});
});
});
});
I've currently got a expressJS app and I'm trying to retrieve information from an API using the getStats
function. However, the profile
route I've written seems to be multiple nested callbacks. How would I prevent this? Is there a way to make it get all of the stats, then assign them to variables after they all of the stats are retrieved?
function getStats(access_token, time_range, x, callback) {
var stats = [];
var options = {
url: 'www.example.',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
json: true
}
request(options, function(error, response, body) {
if (!error && response.statusCode == 200) {
for (i = 0; i < body.items.length; i++) {
stats.push(body.items[i].name);
}
return callback(stats);
}
})
}
app.get('/profile', function(req, res) {
var access_token = 1234;
getStats(access_token, 's', 'x', function(a){
console.log(a);
getStats(access_token, 's', 'y', function(b){
console.log(b);
getStats(access_token, 'm', 'x', function(c){
console.log(c);
getStats(access_token, 'm', 'y', function(d){
console.log(d);
getStats(access_token, 'l', 'x', function(e){
console.log(e);
getStats(access_token, 'l', 'y', function(f){
console.log(f);
res.send(a + "\n" + b + "\n" + c + "\n" + d + "\n" + e + "\n" + f);
});
});
});
});
});
});
});
Share
Improve this question
edited Sep 16, 2018 at 10:58
kockburn
17.7k10 gold badges90 silver badges143 bronze badges
asked Sep 16, 2018 at 10:24
newangnewang
1992 gold badges2 silver badges8 bronze badges
1
- 4 I would suggest that you look into Promises – SeinopSys Commented Sep 16, 2018 at 10:26
3 Answers
Reset to default 7Promises allow you to avoid the type of callback nesting like you've just shown. See my example which illustrates your example in Promise form:
function getStats(access_token, time_range, x, prevResult) {
return new Promise((resolve, reject) => {
if (prevResult) {
resolve([...prevResult, "test", "test", "test"]);
}
return resolve(["test", "test", "test"]);
});
}
app.get('/profile', (req, res) => {
var access_token = 1234;
getStats(access_token, 's', 'x')
.then((a) => {
console.log(a);
return getStats(access_token, 's', 'y', a);
})
.then((b) => {
console.log(b);
return getStats(access_token, 'm', 'x', b);
})
.then((c) => {
console.log(c);
return getStats(access_token, 'm', 'y', c);
})
.then((d) => {
console.log(d);
return getStats(access_token, 'l', 'x', d);
})
.then((e) => {
console.log(e);
return getStats(access_token, 'l', 'y', e);
})
.then((f) => {
console.log(f);
res.send(f.join("\n"));
});
});
As you can see the nested callback structure and replace with a much more readable format. Read more about promises here.
The above could even be rewritten using Promise.all, which looks even nicer:
function getStats(access_token, time_range, x) {
return new Promise((resolve, reject) => {
return resolve(["test", "test", "test"]);
});
}
app.get('/profile', (req, res) => {
var access_token = 1234;
Promise.all([
getStats(access_token, 's', 'x'),
getStats(access_token, 's', 'y'),
getStats(access_token, 'm', 'x'),
getStats(access_token, 'm', 'y'),
getStats(access_token, 'l', 'x'),
getStats(access_token, 'l', 'y')
]).then((values) => {
console.log(values);
res.send(values.join("\n"));
});
});
Promises will help with that, or moving your callbacks into their own function expressions outside of the route, and then calling it in the route once will help.
The problem with that callback hell is that you are not using middlewares where the express app is supporting it.
Basically a way to write an express app is relying in the callbacks and so on. But the counterpart is that this will lead to as what you pointed out the callback hell.
This happens also with promises as well and it's called the promise hell when not properly handled.
The best way to avoid this two patterns are moving into the middlewares solutions.
function getAccesstoken(req, res, next) {
if (!req.something) {
return next('Error, something was not specified');
}
req.someRequestVariable = 'set_something';
next();
}
function processRequest(req, res, next) {
console.log(req.someRequestVariable);
res.send(200);
}
app.use(function genericHandlerForEveryCall() {
console.log('This is being called in every request');
})
app.get('/profile', getAccesstoken, processRequest);
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745430072a4627350.html
评论列表(0条)