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 的精神,我会尝试执行以下不需要任何事务行为的流程:

  1. id = INCR user:id
  2. 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"

惊人,但真实! (线索:)