这是我想简化的示例:
exports.generateUrl = function (req, res) {
var id = req.query.someParameter;
var query = MyMongooseModel.findOne({'id': id});
query.exec(function (err, mongooseModel) {
if(err) {
//deal with it
}
if (!mongooseModel) {
generateUrl(Id,
function (err, text, url) {
if (err) {
res.status(HttpStatus.INTERNAL_SERVER_ERROR).send(err);
return;
}
var newMongooseModel = new AnotherMongooseModel();
newMongooseModel.id = id;
newMongooseModel.save(function (err) {
if (err) {
res.status(HttpStatus.INTERNAL_SERVER_ERROR).send(err);
} else {
res.send({url: url, text: text});
}
});
});
} else {
//deal with already exists
}
});
};
我看过其他 SO 答案,他们告诉您使用命名函数,但没有说明如何处理要传入的变量或使用 jQuery 的队列。我两者都没有。
我知道我可以用命名函数替换我的匿名函数,但是我需要传递周围的变量。例如,如果函数在别处定义,我的内部函数将如何访问 res
?
最佳答案
你的问题的核心是:
I understand that I can replace my anonymous functions with names functions, but then I would need to pass arounds variables. How would my inner function access res for instance if the function is defined elsewhere?
答案是使用函数工厂。
一般来说,这是:
function x (a) {
do_something(function(){
process(a);
});
}
可以转换成这样:
function x (a) {
do_something(y_maker(a)); // notice we're calling y_maker,
// not passing it in as callback
}
function y_maker (b) {
return function () {
process(b);
};
}
在上面的代码中,y_maker
是一个生成函数的函数(我们称该函数的用途为“y”)。在我自己的代码中,我使用命名约定 .._maker
或 generate_..
来表示我正在调用函数工厂。但这只是我的看法,这个约定绝不是标准的,也不是在野外广泛采用的。
因此对于您的代码,您可以将其重构为:
exports.generateUrl = function (req, res) {
var id = req.query.someParameter;
var query = MyMongooseModel.findOne({'id': id});
query.exec(make_queryHandler(req,res));
};
function make_queryHandler (req, res) {
return function (err, mongooseModel) {
if(err) {
//deal with it
}
else if (!mongooseModel) {
generateUrl(Id,make_urlGeneratorHandler(req,res));
} else {
//deal with already exists
}
}}
function make_urlGeneratorHandler (req, res) {
return function (err, text, url) {
if (err) {
res.status(HttpStatus.INTERNAL_SERVER_ERROR).send(err);
return;
}
var newMongooseModel = new AnotherMongooseModel();
newMongooseModel.id = id;
newMongooseModel.save(make_modelSaveHandler(req,res));
}}
function make_modelSaveHandler (req, res) {
return function (err) {
if (err) res.status(HttpStatus.INTERNAL_SERVER_ERROR).send(err);
else res.send({url: url, text: text});
}}
这使嵌套回调变平。作为一个额外的好处,您可以正确命名函数应该做什么。我认为这是很好的做法。
它还有一个额外的优势,它比使用匿名回调要快得多(无论是使用嵌套回调还是使用 promise,尽管如果您将命名函数传递给 promise.then() 而不是匿名函数,那么您将获得同样的加速 yield )。之前的一个 SO 问题(我的 google-fu 今天让我失望了)发现命名函数的速度是 node.js 中匿名函数的两倍多(如果我没记错的话,它快了 5 倍多)。
关于javascript - 避免nodeJs中的回调 hell /将变量传递给内部函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25941010/