我有一个这样的数组:
var names = ['Irina', 'Michael', 'Carl'];
我想使用promises交易将它们插入 redis (我不知道另一种方式)。但我对如何做到这一点很困惑;这是我的代码:
var Promise = require("bluebird");
var redis = require("redis");
Promise.promisifyAll(redis.RedisClient.prototype);
Promise.promisifyAll(redis.Multi.prototype);
var client = redis.createClient(), multi;
var names = ['Irina', 'Michael', 'Carl'];
var result = names.map(function(item) {
client.watch('user:id');
client.getAsync('user:id', function(err, data) {
var multi = client.multi();
var user_id = parseInt(data) + 1;
multi.hmsetAsync('user:' + user_id, 'username', item, 'about', 'love to coding');
multi.incrAsync('user:id');
multi.execAsync(function(err,data){
console.log(data);
});
});
});
Promise.all(result).then(function(response) {
console.log(response);
});
但这不起作用(:
编辑:这是应用程序抛出的错误:
未处理的拒绝错误:ERR错误的“get”命令参数数量
有人,请帮帮我!
编辑2:我已经更改了我的代码,但现在只保存了数组的最后一个值:
client.watch('user:id');
var result = names.map(function(item) {
var multi = client.multi();
client.getAsync('user:id').then(function(value) {
var user_id = parseInt(value) + 1;
return user_id;
}).then(function(user_id) {
multi.hmsetAsync('user:' + user_id, 'username', item, 'about', 'love to coding');
multi.incrAsync('user:id');
}).then(function() {
multi.execAsync().spread(function(err,data){
console.log(data);
});
});
});
编辑3:
使用redis' MONITOR
时,这是输出:
[0 127.0.0.1:54439] "info"
[0 127.0.0.1:54439] "watch" "user:id"
[0 127.0.0.1:54439] "get" "user:id"
[0 127.0.0.1:54439] "get" "user:id"
[0 127.0.0.1:54439] "get" "user:id"
[0 127.0.0.1:54439] "MULTI"
[0 127.0.0.1:54439] "hmset" "user:88" "username" "Irina" "about" "love to coding"
[0 127.0.0.1:54439] "incr" "user:id"
[0 127.0.0.1:54439] "EXEC"
[0 127.0.0.1:54439] "MULTI"
[0 127.0.0.1:54439] "hmset" "user:88" "username" "Michael" "about" "love to coding"
[0 127.0.0.1:54439] "incr" "user:id"
[0 127.0.0.1:54439] "EXEC"
[0 127.0.0.1:54439] "MULTI"
[0 127.0.0.1:54439] "hmset" "user:88" "username" "Carl" "about" "love to coding"
[0 127.0.0.1:54439] "incr" "user:id"
[0 127.0.0.1:54439] "EXEC"
执行get user:id
3次,然后执行其他方法。为什么呢?
答案 0 :(得分:2)
我用这种方式解决了我的问题:
client.watch('user:id');
Promise.each(names, function(item) {
var multi = client.multi();
return client.getAsync('user:id').then(function(value) {
var user_id = parseInt(value) + 1;
return user_id;
}).then(function(user_id) {
multi.hmsetAsync('user:' + user_id, 'username', item, 'about', 'love to coding');
multi.incrAsync('user:id');
}).then(function() {
return multi.execAsync().spread(function(err,data){
console.log(data);
});
});
})
.then(function() {
console.log("Ended process ...");
});
诀窍是改变:
var result = names.map(function(item) {...});
承诺:
Promise.each(names, function(item) {...});
然后将client.getAsync(user:id)
返回给它。
这是redis'MONITOR:
的输出[0 127.0.0.1:53290] "info"
[0 127.0.0.1:53290] "watch" "user:id"
[0 127.0.0.1:53290] "get" "user:id"
[0 127.0.0.1:53290] "MULTI"
[0 127.0.0.1:53290] "hmset" "user:88" "username" "Irina" "about" "love to coding"
[0 127.0.0.1:53290] "incr" "user:id"
[0 127.0.0.1:53290] "EXEC"
[0 127.0.0.1:53290] "get" "user:id"
[0 127.0.0.1:53290] "MULTI"
[0 127.0.0.1:53290] "hmset" "user:89" "username" "Michael" "about" "love to coding"
[0 127.0.0.1:53290] "incr" "user:id"
[0 127.0.0.1:53290] "EXEC"
[0 127.0.0.1:53290] "get" "user:id"
[0 127.0.0.1:53290] "MULTI"
[0 127.0.0.1:53290] "hmset" "user:90" "username" "Carl" "about" "love to coding"
[0 127.0.0.1:53290] "incr" "user:id"
[0 127.0.0.1:53290] "EXEC"
太棒了,但是真的! (线索:https://stackoverflow.com/a/25129878/2954267)
答案 1 :(得分:0)
免责声明:不是JS maven,但我会尝试帮助:)
看起来您希望每个名称都有一个唯一的ID。本着KISS的精神,我会尝试执行以下不需要任何事务行为的流程:
这里的“风险”是,如果你的工人死于1& 2,你“花”一个ID。如果你可以忍受这种情况,你可能应该看起来像这样(对不起,未经测试 - 见免责声明;)):
var result = names.map(function(item) {
client.incrAsync('user:id').then(function(user_id) {
client.hmsetAsync('user:' + parseInt(user_id), 'username', item, 'about', 'love to coding');
}).then(function(err) {
console.log(err);
});
});
更新1 :但由于您正在修改for for,我猜测姓氏的更新,特别是对INCR的调用,打破了以前的更新的WATCH。由于您没有导致错误,因此您没有看到此错误。您还可以在执行代码时使用Redis'MONITOR
来调试行为。
更新2 :我猜这是Node如何处理异步 - 首先它会触发GET并在需要等待响应时停止。然后第一个响应(到第一个GET)被处理,然后是第二个...除了弄乱你的预期逻辑,这也导致只有第一个批量享受MULTI - 其他两个没有在他们的之前没有MULTI声明相对执行。