各位午安,方才我在进行 node 上头的 MySQL query,发现了一些问题,请先见程式码如下。
var getAllCouponsInfoByManagerUidAndRange = function (uid, range, callback) {
// Select the special range in coupons, the range object have 'start' and 'amount'.
var sql_1 = "SELECT * FROM coupon WHERE coupon_id BETWEEN " + range.start + " AND " + (range.start + range.amount - 1);
dbclient.query(sql_1, function (err, coupons) {
// Fixed the properties.
coupons = TaskDateConvertToJson(coupons, new Array("create_time", "used_time"));
for (var i = 0 ; i < coupons.length ; i++) {
(function (j) {
// Get the employees' user info of having received coupons.
findUserByUid(coupons[j].uid, function (employee) {
// Get the managers of creating coupons.
findUserByUid(coupons[j].manager, function (manager) {
// Get the employees' task info of having received coupons.
findTaskByTid(coupons[j].tid, function (task) {
coupons[j]['employee'] = employee;
coupons[j]['manager'] = manager;
coupons[j]['task'] = task;
delete coupons[j]['uid'];
delete coupons[j]['tid'];
if (j == coupons.length - 1)
callback(coupons);
console.log(coupons[j]);
});
});
});
})(i);
}
});
}
其中有一行
console.log(coupons[j]);
是用来检查 query 的执行完毕顺序,
假使目前情况是 15 笔到 30 笔,因为部分条件不同,console.log 的结果会发现
15, 16, 18, 19, … , 30, 17。
第 17 笔经过较多层的 query 所以回传的时间较久,因为这样:
if (j == coupons.length - 1)
callback(coupons);
在完成第 30 笔时就执行 callback …其中回传的第 17 笔是没有 query 的结果。
还麻烦各位前辈协助解答,感谢!
@alsotang 谢谢前辈回覆,采用同步类型的套件应该不是解决我当前遇到的问题,我用了一点土法炼钢的方式解决了,看完的话您大概会知道我遇到的问题XD
var SQLQueryCheck = {
createArrayInit: function (size) {
var arr = new Array();
for (var i = 0 ; i < size ; i++)
arr[i] = false;
return arr;
},
checkedAllQueried: function(arr) {
for (var i = 0 ; i < arr.length ; i++)
if (arr[i] === false)
return false;
return true;
}
}
var getAllCouponsInfoByManagerUidAndRange = function (uid, range, callback) {
// Select the special range in coupons, the range object have 'start' and 'amount'.
var sql_1 = "SELECT * FROM coupon WHERE coupon_id BETWEEN " + range.start + " AND " + (range.start + range.amount - 1);
dbclient.query(sql_1, function (err, coupons) {
// Fixed the properties.
coupons = TaskDateConvertToJson(coupons, new Array("create_time", "used_time"));
var queryChecked = SQLQueryCheck.createArrayInit(coupons.length);
for (var i = 0 ; i < coupons.length ; i++) {
(function (j) {
// Get the employees' user info of having received coupons.
findUserByUid(coupons[j].uid, function (employee) {
// Get the managers of creating coupons.
findUserByUid(coupons[j].manager, function (manager) {
// Get the employees' task info of having received coupons.
findTaskByTid(coupons[j].tid, function (task) {
coupons[j]['employee'] = employee;
coupons[j]['manager'] = manager;
coupons[j]['task'] = task;
delete coupons[j]['uid'];
delete coupons[j]['tid'];
queryChecked[j] = true;
if (SQLQueryCheck.checkedAllQueried(queryChecked))
callback(coupons);
});
});
});
})(i);
}
});
}
我仔细看了下代码 这是典型的异步回调场景啊。 楼主无非是想 全部query执行完毕再回调,所以自己写了个函数,每次检查各个query的执行状态。 解决方法没问题,不过还是推荐直接eventproxy一行代码就搞定了。 就不用每次自己写函数了。
顺便,一般在不会遍历所有键的情况下(也就是说不会出特别严谨错误的使用姿势的时候),建议用 = undefined
代替 delete
。
不过这个是我自己的看法而已,只是推荐这样用。
http://www.smashingmagazine.com/2012/11/05/writing-fast-memory-efficient-javascript/
@grass0916 看下面的段落: 重复异步协作
此处以读取目录下的所有文件为例,在异步操作中,我们需要在所有异步调用结束后,执行某些操作。
var ep = new EventProxy(); ep.after('got_file’, files.length, function (list) { // 在所有文件的异步执行结束后将被执行 // 所有文件的内容都存在list数组中 }); for (var i = 0; i < files.length; i++) { fs.readFile(files[i], 'utf-8’, function (err, content) { // 触发结果事件 ep.emit('got_file’, content); }); }
更具体的参考github
用howdo帮你重写了一遍
var howdo = require('howdo');
var getAllCouponsInfoByManagerUidAndRange2 = function(uid, range, callback) {
// Select the special range in coupons, the range object have 'start' and 'amount'.
var sql_1 = 'SELECT * FROM coupon WHERE coupon_id BETWEEN ' + range.start + ' AND ' + (range.start + range.amount - 1);
dbclient.query(sql_1, function(err, coupons) {
if (err) {
return callback(err);
}
// Fixed the properties.
var coupons = TaskDateConvertToJson(coupons, ['create_time', 'used_time']);
howdo.each(coupons, function(index, coupon, done) {
howdo
// Get the employees' user info of having received coupons.
.task(function(done) {
findUserByUid(coupon.uid, function(employee) {
done(null, employee);
});
})
// Get the managers of creating coupons.
.task(function(done) {
findUserByUid(coupon.manager, function(manager) {
done(null, manager);
});
})
// Get the employees' task info of having received coupons.
.task(function(done) {
findTaskByTid(coupon.tid, function(task) {
done(null, task);
});
})
// 并行无依赖结果
.together(function(err, employee, manager, task) {
coupon.employee = employee;
coupon.manager = manager;
coupon.task = task;
delete coupon.uid;
delete coupon.tid;
done(null, coupon);
});
}).together(function(err, create_time, used_time) {
// 做你该做的
// ....
callback(err, create_time, used_time);
});
});
};