格式如下: async.each(role,function(name, cb){ redisClient.get(name,function(err,roleReply){ 。。。。 }) });
async.each(dept,function(name, cb){ redisClient.get(name,function(err,deptReply){ 。。。。。 }) });
分别存在role 以及dept的数组 现根据async,循环从redis中取数据,如何实现这两个函数并行执行,而且知道他们已经执行完成??
如果你用 Promise:
Promise.all([
roles.map(redis.getAsync.bind(redis)),
depts.map(redis.getAsync.bind(redis))
])
.then(function(result) {
// results[0] ==> roles
// results[1] ==> depts
})
.getAsync
是 bluebird 给 redis client 自动封装的返回 promise 的函数。
function roll (nums, f) {
var count = nums;
return function () {
count--;
if (count === 0) {
f.call(null);
}
};
}
var test = function () { console.log('ok.') };
var rollInstance = roll(2, test);
async.each(role,function(name, cb){
redisClient.get(name,function(err,roleReply){
。。。。
rollInstance();
});
});
async.each(dept,function(name, cb){
redisClient.get(name,function(err,deptReply){
。。。。。
rollInstance();
});
});
能不能不通过计数的方式实现啊 ?
由于是初学者,能否再 说的仔细点呢??
async.parallel
和 async.map
可以帮上忙。 试试下面的代码,没有环境未测试,大概是这个意思。
async.parallel([
function(callback) { // task#1
async.map(role, function(name, cb) {
redisClient.get(name,function(err,roleReply){
cb(err, roleReply);
});
}, function(err, roles) {
callback(err, roles);
});
},
function(callback){ // your second task
}
],
function(err, results){
// go and play with results
});
@hsh075623201 做梦吧!你要是学过C语言,就知道,最终都要计数,计算机才能识别。 你用的框架,内部也不过是计数而已。
JS解释到C,C对字符数组都要用末尾‘\0’和指定长度来确认字符串结束。
@GuoZhang 请问如下代码有问题嘛 ?我现在采用了如下方法,但不确定是否可以 由于都是数组,因此我先将数组合并了。。 var getValuesByKey = { getValue:function(key,callback){ var retVal=[]; redisClient.get(key,function(err,roleReply){ for(var i=0;i<JSON.parse(roleReply).component.length;i++){ … retVal.push(); } callback(null, retVal); }) } }
async.map(redisKey, getValuesByKey.getValue.bind(getValuesByKey), function(err, result){ … });
@hsh075623201 感觉没有问题,你实际使用一下吧。
getValuesByKey.getValue.bind(getValuesByKey)
在你的情况下似乎没有必要,因为不存在getValue()
没有使用this
,可以简单地试着写成:
function getValue(key, callback) {
....
}
async.map(redisKey, getValue, function (err, result) {
...
});
或直接匿名:
async.map(redisKey, function(key, callback) {
...
}, function (err, result) {
...
});
嗯 好的 谢谢!
@GuoZhang 你好 再次咨询下 代码如下: async.map(MenuPages, function(menuPage, callback) { … menuPage.save(); callback(null); }, function (err, result) { res.json(“success”); }); 我想要完成的是 将menuPages存入数据库 ,然后 返回success 但是上述方法返回后 有时候数据只存入一些,没有全部存入,应该怎么解决呢? 使用mongoose提供的create方法也出现这个问题 ,如下所示: Menu.create(MenuPages,function(err, result){ res.json(“success”); });
@hsh075623201 从你给出来的代码,不太能看到错误。
menuPage.save(); // 同步的还是异步的?感觉应该是异步
callback(null); // 如果是的话,callback可能会在menuPage保存完成前调用
另外:
将menuPages存入数据库 ,然后 返回success – 在这种情况下,你似乎不需要每个menuPage保存后的返回值,因此,可以不使用async.map
而是使用async.each
。
简单写了个例子:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var async = require('async');
mongoose.connect('mongodb://localhost:27017/test');
// define model
var User = mongoose.model('User', new Schema({
name: String
}));
// create users
var users = [];
for (var i = 0; i < 5; ++i) {
users.push({ name: 'user#' + i });
}
// and save them
async.each(users, function (user, callback) {
User.create(user, function (err, user) {
callback(err);
});
}, function (err) {
if (err) {
console.log('Error: ' + err);
} else {
console.log('Done');
}
// disconnect if you intend to
// mongoose.disconnect();
});
执行后查看数据库:
> db.users.find().pretty();
{
"name" : "user#0",
"_id" : ObjectId("53a1ad5d400b2aa6044c7afd"),
"__v" : 0
}
{
"name" : "user#2",
"_id" : ObjectId("53a1ad5d400b2aa6044c7aff"),
"__v" : 0
}
{
"name" : "user#1",
"_id" : ObjectId("53a1ad5d400b2aa6044c7afe"),
"__v" : 0
}
{
"name" : "user#3",
"_id" : ObjectId("53a1ad5d400b2aa6044c7b00"),
"__v" : 0
}
{
"name" : "user#4",
"_id" : ObjectId("53a1ad5d400b2aa6044c7b01"),
"__v" : 0
}
@GuoZhang 你好,我还有些疑问,感觉你贴出来的代码 和我的思路差不多 ,你这段代码不是也将一个个数据保存至数据库,导致还没保存完 就调用callback,是我理解错了吗?
导致还没保存完 就调用callback
User.create(user, function (err, user) {
callback(err); // 这个callback是对保存数组中的每一项的回调 -- 这里就是这个user的处理是否成功还是有错误
// 而不是针对这个数组中的所有元素是否处理完成的
});
所有元素处理完毕的回调在这里:
function (err) { // 所有元素处理完毕了(也不见得一定是处理了所有元素)
if (err) { // 如果处理某个元素时错误(callback(err) 时,这个err不为空),会立马跳到这里
// 并且这里的err就是callback(err)时的那个err
console.log('Error: ' + err);
} else { // 如果执行到了这里,表示数组中的所有元素已经成功地处理完毕
console.log('Done');
}
附上async.each的源码,你体会一下:
async.each = function (arr, iterator, callback) {
callback = callback || function () {};
if (!arr.length) { // 如果给的不是array-like参数
return callback(); // 直接回调,做不下去了
}
var completed = 0; // 计数,有多少个元素被成功处理了
_each(arr, function (x) { // 遍历arr中的所有元素 (_each只是利用了Array.prototype.forEach
// 或自己for循环遍历(如果Array.prototype.forEach不存在))
iterator(x, only_once(done) ); // 调用你的迭代函数处理数组中的每一个元素, 这个调用决定了
// 1) 你的迭代函数的第一个参数是数组中的某元素
// 2) 你的迭代函数的第二个参数是一个函数(值为only_once(done))
// only_once保证了你只能调用这个函数至多一次。根据函数done的实现,你必须
// 在你的迭代函数中调用他一次,无论成功还是失败,否则计数completed在没有错误的情况
// 下不会+1, 导致最终的callback不能执行 -- 具体看done函数
});
function done(err) {
if (err) { // 如果有错,立马回调 -- 报错
callback(err);
callback = function () {}; // 保证callback也只能被执行一次(想象如果有多个错误同时回调的情况)
}
else {
completed += 1; // 没错,计数+1
if (completed >= arr.length) { // 如果所有的处理都没有错
callback(); // 回调,处理完毕且无错误
}
}
}
};
@GuoZhang 你好 上面的那个问题 我都过create 方法搞定了 mongoose api [Model.create(doc(s), [fn])], 但是关于异步的疑问仍在 。。。我使用如下方法查询数据,并将有用的数据 返回 ,出现问题 1.返回的有时候 有值 ,有时候没有值 2.不管返回的有值 还是无值 ,打印的地方都没值 。。。 async.map(redisKey, function(key,callback){ var retVal=[]; redisClient.get(key,function(err,roleReply){ for(var i=0;i<JSON.parse(roleReply).menu.length;i++){ for(var j=0;j<docs.length;j++){ … retVal.push(docs[j]); } } callback(null, retVal); }) }, function(err, result){ if(err){ … }else{ var resultArray =[]; for(var i=0;i<result.length;i++){ resultArray = resultArray.concat(result[i]); } console.error(“menu list:”+JSON.stringify(resultArray)); //不管 返回的是有值 还是 无值 这里打印的只有 “[]” res.json(resultArray); }
});
@GuoZhang 我可能找到原因了 我先自己看看 ,非常感谢你的耐心指导!