Javascript node.js回调函数变量范围问题
我正在重新学习Javascript,上周在为大学作业编写这段代码时,我认为可能有更好的方法来执行这段代码Javascript node.js回调函数变量范围问题,javascript,node.js,Javascript,Node.js,我正在重新学习Javascript,上周在为大学作业编写这段代码时,我认为可能有更好的方法来执行这段代码 app.get('/member/all', function(req, res) { connection.query('CALL GetAllMembers()', function(err,rows){ connection.query('CALL CountMembers()', function(err, allMembers){
app.get('/member/all', function(req, res) {
connection.query('CALL GetAllMembers()', function(err,rows){
connection.query('CALL CountMembers()', function(err, allMembers){
console.log(err);
connection.query('CALL CountAllIndMembers()', function(err,indMembers){
console.log(err);
connection.query('CALL CountInactiveMembers()', function(err,inactiveMembers){
console.log(err);
connection.query('CALL CountAllMembersInGroups()', function(err,groupMembers){
console.log(err);
res.render('members', {members : rows[0], title : "All Members", groupMembers : groupMembers[0][0].AllGrpMembers,
inactiveMembers : inactiveMembers[0][0].AllInactiveMembers, indMembers : indMembers[0][0].AllIndMembers,
allMembers : allMembers[0][0].AllMembers, statistics : true});
});
});
});
});
});
});
});
当我试图在app.get
下声明变量时,比如var allMembers
。。。执行回调时,我无法从回调中设置allMembers=rows
。它似乎是回调的一个局部变量。我确信这与可变范围和/或吊装有关。我只是想问你们是否有更好的方法来实现这一点,即使这个函数可以工作。这是非常丑陋的看哈哈
提前谢谢
Jack就作用域而言,所有内部函数都应该能够读取和写入外部变量,除非它被内部变量声明或函数参数隐藏 您遇到的问题可能与代码的异步性有关。请参阅此代码:
function delay(n, cb){
setTimeout(function(){ bs(delay) }, delay);
}
function main(){
var allMembers = 17;
delay(500, function(){
console.log(allMembers); // This looks at the outer "allMembers"
allMembers = 18;
delay(200, function(allMembers){ // <-- SHADOW
console.log(allMembers); // This looks at the allMembers from "delay 200"'s callback
allMembers = 42;
});
delay(300, function(){
console.log(allMembers); //This is the outside "allMembers" again
});
});
return allMembers; // Still 17!
}
main();
请参阅异步库:
如果函数的执行顺序无关紧要,则可以使用async.parallel而不是async.series。使用库处理和封装与异步调用的“”(CPS)交互是有力量的。下面的代码不是来自库,但我将详细介绍它,并将其作为实现CPS的一种方法的示例 第一步是设置适用于范围的队列。本例使用了最简单的方法:
var nextList = [];
之后,我们需要一种方法来处理第一种情况,即需要对将来要执行的任务进行排队。在本例中,我专注于按顺序执行它们,因此我将其命名为next
function next() {
var todo,
current,
task,
args = {};
if (arguments.length > 0) { // if called with parameters process them
// if parameters aren't in an array wrap them
if (!Array.isArray(arguments['0'])) {
todo = [arguments];
} else { // we were passed an array
todo = [];
arguments['0'].forEach(function (item) {
// for each item we were passed add it to todo
todo.push(item);
});
}
nextList = todo.concat(nextList);
// append the new items to the end of our list
}
if (nextList.length > 0) { // if there are still things to do
current = Array.prototype.slice.apply(nextList.shift());
task = current[0];
args = current.slice(1);
task.apply(null, args); // execute the next item in the list
}
}
这使我们可以拨打如下电话:
.map(function (filepath) {
tasks.push(
[
handleAsset,
{
'path': filepath,
}
]
);
});
tasks.push([done]);
next(tasks);
这将按顺序为每个文件调用一次异步handleAsset。这将允许您使用代码,并将每个嵌套调用更改为以下形式的单独函数:
function memberAll() {
app.get('/member/all', function(req, res) {
if (err) {
handleError(err, 'memberAll');
} else {
next(getAllMembers, 'parameters to that call if needed');
}
});
}
其中,handleError
是一个常见的错误处理程序,下一个调用允许您将相关参数传递给所需的下一个函数。重要的是,在if
语句的成功端,您可以:
- 有条件地调用几个函数中的一个
- 使用一系列调用调用调用next,例如,如果您有用于
和processFolder
的函数,则处理文件夹可能会涉及处理其他文件夹和文件,并且数量会有所不同processFile
- 除了调用无参数的
并结束当前分支外,不执行任何操作next()
修饰可以包括编写一个清空
nextList
的干净函数,将项目添加到nextList
,而不调用列表中的项目,在这一点上,另一种选择是使用现有库进行此操作,或者继续编写您自己的库。使它们成为所有函数,而不是匿名调用它们!代码的丑陋是节点回调的一个不幸的副作用。我建议看一看涉及生成器的内容(yield关键字而不是回调),但不知道是否足够稳定,可以在节点中使用。如果您想要更传统的内容,可以查看诸如async.js之类的lib,或者使用PromisesReading了解“Contination传递样式”在这一点上,这将大大增加您的理解。感谢您为我澄清了这一点:)当需要对数据库进行一系列调用时,其中每个后续调用都取决于上一次调用的返回,此方法将导致性能不佳。更糟糕的是,如果选择的延迟时间不够长,它将失败。增加延迟只会使性能更差。@jasonaler:我打算将延迟函数作为一个简单的异步函数,您可以使用它在没有DB的情况下测试内容,并演示变量范围。是的,我不建议使用实际延迟来等待DB响应(事实上,嵌套的DB调用通常是一种气味——如果没有一种方法可以通过jsut单次查询获得相同的数据,这总是值得研究的)。很抱歉,我在第一次通读时错过了您的一些答案。当我通读你的答案时,我正专注于问题的另一个方面。
.map(function (filepath) {
tasks.push(
[
handleAsset,
{
'path': filepath,
}
]
);
});
tasks.push([done]);
next(tasks);
function memberAll() {
app.get('/member/all', function(req, res) {
if (err) {
handleError(err, 'memberAll');
} else {
next(getAllMembers, 'parameters to that call if needed');
}
});
}