Redis - 在具有承诺的事务中插入数组中的值(蓝鸟)
Redis - Insert values from array in a transaction with promises (bluebird)
我有一个这样的数组:
var names = ['Irina', 'Michael', 'Carl'];
我想使用承诺交易将它们插入 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次,然后执行其他方法。为什么?
免责声明:我不是 JS 专家,但我会尽力提供帮助:)
您似乎希望每个名称都有一个唯一的 ID。本着 KISS 的精神,我会尝试执行以下不需要任何事务行为的流程:
- id = INCR user:id
- HMSET 用户:...
这里的"risk"是如果你的工人在1和2之间死了,你"spend"一个ID。如果你能接受它,你的 could 应该看起来像这样(抱歉,未经测试 - 请参阅免责声明;)):
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 交易,我猜测姓氏的更新,特别是对 INCR 的调用,打破了之前的 WATCH那些。由于您没有导致错误,因此您没有看到这一点。您还可以在执行代码时使用 Redis 的 MONITOR
来调试行为。
更新 2:我猜这就是 Node 处理异步事务的方式 - 首先它触发 GET 并在需要等待响应时停止。然后处理第一个响应(对第一个 GET),然后是第二个...除了扰乱您的预期逻辑之外,这还会导致只有第一个批量享受 MULTI - 其他两个在它们之前没有 MULTI 语句相关执行人员。
我是这样解决问题的:
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) {...});
然后 return 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"
惊人,但真实! (线索:)
我有一个这样的数组:
var names = ['Irina', 'Michael', 'Carl'];
我想使用承诺交易将它们插入 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次,然后执行其他方法。为什么?
免责声明:我不是 JS 专家,但我会尽力提供帮助:)
您似乎希望每个名称都有一个唯一的 ID。本着 KISS 的精神,我会尝试执行以下不需要任何事务行为的流程:
- id = INCR user:id
- HMSET 用户:...
这里的"risk"是如果你的工人在1和2之间死了,你"spend"一个ID。如果你能接受它,你的 could 应该看起来像这样(抱歉,未经测试 - 请参阅免责声明;)):
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 交易,我猜测姓氏的更新,特别是对 INCR 的调用,打破了之前的 WATCH那些。由于您没有导致错误,因此您没有看到这一点。您还可以在执行代码时使用 Redis 的 MONITOR
来调试行为。
更新 2:我猜这就是 Node 处理异步事务的方式 - 首先它触发 GET 并在需要等待响应时停止。然后处理第一个响应(对第一个 GET),然后是第二个...除了扰乱您的预期逻辑之外,这还会导致只有第一个批量享受 MULTI - 其他两个在它们之前没有 MULTI 语句相关执行人员。
我是这样解决问题的:
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) {...});
然后 return 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"
惊人,但真实! (线索:)