在 User_UidSearch 函式当中我想要取用上一层 for 回圈的i ,但没有办法,这个 i 的scope 让我有点疑惑,不晓得各位前辈有没有不使用全域变数的解决办法呢?
Task_TidSearchExecution = function(tid, callback) {
var sql = "SELECT * FROM execution WHERE task = '" + tid + "'";
dbclient.query(sql, function (err, results) {
if (err || results.length <= 0)
callback(false);
else {
console.log(results.length);
for (var i = 0 ; i < results.length ; i++) {
User_UidSearch(results[i].employee, function (user) {
console.log(i);
// results[i]['email'] = user.email;
});
}
callback(results);
}
});
}
console.log(result[i]); 输出都是 undefined。 如果我的 results.length 为 2,console.log(i); 都是 2
经典问题。
for (var i = 0 ; i < results.length ; i++) {
(function (j) {
User_UidSearch(results[j].employee, function (user) {
console.log(j);
// results[j]['email'] = user.email;
});
})(i);
};
主要思路就是,把 i 变成局部变量,而不是引用,就好了。
@alsotang 感谢大侠帮助,成功的让 i 进去该 callback 中。 我想应该是我javascript 学艺不精,请问这个方法有什么名称吗?
@grass0916 闭包
@chloe 谢谢前辈。 现在衍生了其他后续问题,待我修正后再一次把问题的解法程式码更新到文章中。
经过前辈们指教,解决的上述的问题,以及衍生出来的问题。
程式码如下,不过觉得可读性有点低,想请教有没有更精炼的优化方式。
Task_TidSearchExecution = function(tid, callback) {
var sql = "SELECT * FROM execution WHERE task = '" + tid + "'";
dbclient.query(sql, function (err, results) {
if (err || results.length <= 0)
callback(false);
else {
AddEmployeesInfo(function (results) {
console.log(results);
callback(results);
});
function AddEmployeesInfo(callback) {
for (var i = 0 ; i < results.length ; i++) {
(function (j) {
User_UidSearch(results[j].employee, function (user) {
results[j]['uid'] = user.uid;
results[j]['email'] = user.email;
if (j == results.length-1)
callback(results);
});
})(i);
}
};
}
});
}
看这术语用的你是台湾人吗?
@ravenwang 是的
我有几个建议。
对于 Task_TidSearchExecution = function(tid, callback)
:
- 改成
var Task_TidSearchExecution = function(tid, callback)
; - 函数的命名风格保持一致,参照下面的
AddEmployeesInfo
,把Task_TidSearchExecution
改为findExecutionTaskById
更自然点; - 这里的函数参数
callback
没有遵循Node.js的例行写法。一般来说,callback函数都被定义成callback(err, arg1, arg2, ...)
的形式。因此,建议把callback
的函数原型修改为callback(err, results)
; - 函数体里,
if (err || results.length<=0)
中没必要添加results.length<=0
的判断; else
部分,AddEmployeesInfo
函数的定义似乎是多此一举,直接在else
下面写for
循环的语句就可以了;- 不了解数据库表和
User_UidSearch
函数的定义,更多优化无从下手。感觉有进一步优化的空间。
@ravenwang 我都没发现这点,经你一提醒,看了看还真是台湾术语
@alsotang 大家不会排斥我吧 … ? Q_Q
@bnuhero 前辈早安,根据你宝贵的建议我尝试做了一些更动,还请你审视一番。
- “Task_” 系列函数是 SQL query 用途,所以他们本身是属最外层,所以我就没有多留意加上var,虽然不影响结果但想起曾经看过一篇文章「变数通通都加上var」这类的观念。
- 对,其实一致也会比较好,那我就更改了。
- 这点其实我不太清楚,麻烦你再帮忙解释了 ><
- 由于 query 的结果可能会有程式码执行成功但无资料回传,所以仍必须写上 length == 0,不过我改了一下写法,可以看看文后的程式码。
- 逻辑问题,抱歉还不是很熟callback,我修正了@@
- 于后面附上
/* =============================================
Task - Employer maintain tasks
============================================= */
app.get('/maintain_task', function (req, res) {
// Users can see this page when them logged-in.
if (req.session) {
var user = { "uid": req.session.uid, "email": req.session.email };
var query_tid = req.query.tid;
findEmployerByTid(query_tid, function (manager) {
// If this task manager matches on user's id.
if (manager !== false && user.uid === manager) {
// Get the task info.
findTaskByTid(query_tid, function (task) {
// Get these executions info with employees' info.
findExecutionTaskByTid(task.tid, function (employees) {
res.render("task_system/maintain_task", {
layout: false,
pagename: "Page Name",
user: user,
task: task,
employees: employees,
errormessage: "null"
});
});
});
}
// If this task manager no matches on user's id.
else
res.redirect('/employer_task_list');
});
}
// Users must log in first.
else
res.redirect('/login');
});
var findExecutionTaskByTid = function(tid, callback) {
var sql = "SELECT * FROM execution WHERE task = '" + tid + "'";
dbclient.query(sql, function (err, results) {
if (err)
callback(false);
else if (results.length == 0)
callback(new Array());
for (var i = 0 ; i < results.length ; i++) {
(function (j) {
findUserByUid(results[j].employee, function (user) {
results[j]['uid'] = user.uid;
results[j]['email'] = user.email;
if (j == results.length-1)
callback(results);
});
})(i);
}
});
}
var findUserByUid = function (uid, callback) {
var sql = "SELECT * FROM user WHERE uid = '" + uid + "'";
dbclient.query(sql, function (err, results) {
if (err || results.length <= 0)
callback(false);
else
callback(results[0]);
});
}
var findTaskByTid = function (tid, callback) {
var sql = "SELECT * FROM task WHERE tid = '" + tid +"'";
dbclient.query(sql, function (err, results) {
if (err || results.length <= 0)
callback(false);
else
callback(results[0]);
});
}
var findEmployerByTid = function (tid, callback) {
var sql = "SELECT employer FROM task WHERE tid = '" + tid +"'";
dbclient.query(sql, function (err, results) {
if (err || results.length <= 0)
callback(false);
else
callback(results[0].employer);
});
}
@grass0916 那倒不会…只是我平时很少见到那些翻译
@grass0916 欢迎台湾同胞:)
@ravenwang @alsotang 谢谢大家不嫌弃 <(_ _ *)>
关于回调函数的惯常写法,举个例子。
// 通常回调函数的第一个参数是一个Error对象。
var printNumber = function(err, num) {
if (err) {
console.error(err);
} else {
console.log(num);
};
};
// 主函数
var getNumber = function(callback) {
// 从数据库中读取数据
// 如果读取过程中出错了,
callback(new Error('Something is wrong'));
// 否则,假设读到的数据保存在num变量中,
callback(null, num);
};
// 调用主函数
getNumber(printNumber);
像你的代码中的callback
,把代表出错信息的对象和正常结果的对象用同一个参数表示,不符合如上所述的惯常用法。