我正在重新学习Javascript,上周在为大学作业编写此代码时,我认为可能有更好的方法来执行此代码
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 = rowsFromTheCallback
。它似乎是该回调的局部变量。我确定这与变量范围和/或提升有关。只是想问你们是否有更好的方法来做到这一点,即使这个功能有效。看哈哈真是太难看了!
提前致谢
杰克
答案 0 :(得分:1)
就范围而言,所有内部函数都应该能够读取和写入外部变量,除非它被内部变量声明或函数参数遮蔽。
您遇到的问题可能与代码的异步有关。看到这段代码:
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();
main
将在setTimeouts被触发之前返回,因此它将返回该变量的原始值。为了等待内部回调运行,唯一的方法是让main
在完成后对signa进行回调,而不是仅仅返回。
function main(onResult){
delay(500, function(){
//...
onResult(allMembers);
});
// <-- no return value
});
main(function(allM){
console.log(allM);
});
答案 1 :(得分:1)
请参阅异步库:https://github.com/caolan/async
async.series([
getAllMembers,
countMembers,
...
], function(err, results) {
// err contains an error if any of the functions fails. No more functions will be run.
// results is an array containing results of each function if all the functions executed without errors
}));
function getAllMembers(callback) {
connection.query('CALL CountMembers()', callback);
}
function countMembers(callback) {
...
}
如果函数的执行顺序无关紧要,可以使用async.parallel代替async.series。
答案 2 :(得分:0)
使用库来处理和封装&#34; Continuation Passing Style&#34; (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
语句的成功方面,您可以:
processFolder
和processFile
的函数,您可以预期处理文件夹可能涉及处理其他文件夹和文件,并且该编号将会变化next()
并且结束当前分支装饰可以包括编写一个清理函数来清空nextList
,将项目添加到nextList
而不调用列表中的项目等。此时的替代方法是使用现有库这或继续写自己的。