Rumah > pangkalan data > tutorial mysql > 在异步回调中操作redis的一个异常

在异步回调中操作redis的一个异常

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
Lepaskan: 2016-06-07 16:38:28
asal
1732 orang telah melayarinya

昨天在使用node redis的时候报了这样一个错: TypeError: Object [object Object] has no method 'send_command' at RedisClient.(anonymous function) (D:\index.js:991:25) at null._onTimeout (D:\index.js:17:22) at Timer.listOnTimeout [as ontimeout]

昨天在使用node redis的时候报了这样一个错:

TypeError: Object [object Object] has no method 'send_command'
    at RedisClient.(anonymous function) (D:\index.js:991:25)
    at null._onTimeout (D:\index.js:17:22)
    at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)
Salin selepas log masuk

这个bug比较隐蔽,一步一步来看:

起因

我要实现的是批量插入redis的列表(list),相关的api是这样的:client.rpush(key, [value1, value2, ..., callback]) ,参数必须一个一个列出来,要想批量添加(数组),只能使用apply 方法了:

var array = ['list', '1', '2', '3', '4',
    function() {
        console.log('success');
    }
];
client.rpush.apply(this, array);
Salin selepas log masuk

数组的第一参数是key,最后一个是回调函数,之间全部是要添加的数据。构造这样一个数组,使用apply 就很完美的解决了批量添加的问题。但是还是太年轻啊,执行demo的时候很正常,但是放入正式代码中就有问题了。

解决

正式代码的数据一般是异步得到的,用setTimeout 模拟一下:

var redis = require('redis'),
    client = redis.createClient(6379, '127.0.0.1', {
        auth_pass: 'home.local.17173.com'
    });
client.on('error', function(err) {
    console.log('redis错误:' + err);
});
client.on('connect', function() {
    setTimeout(function() {
        var array = ['list', '1', '2', '3', '4',
            function() {
                console.log('success');
            }
        ];
        client.rpush.apply(this, array);
    }, 1000);
});
Salin selepas log masuk

执行上面的代码会报出文章开头的错误,提示“Object [object Object] has no method ‘send_command’”,联系到apply 的this,问题可能出在作用域上,修改倒数第三行代码:

client.rpush.apply(client, array);
Salin selepas log masuk

执行后就ok了:

所以问题就是出在作用域上,apply 这样的比较明显,但是使用async等就不是那么明显了。在stackoverflow上找到一个问题,有bug的代码是这样的:

var async = require('async');
var redis = require('redis');
var keys = ['key1', 'key2', 'key3'];
var client = redis.createClient();
var multi = client.multi();
for (var key in keys) {
  multi.hmset(key, {'some': 'value'});
}
multi.exec(function(err, res) {
  if (err) throw err;
  console.dir(res);
  var myCallback = function(err, res) {
    console.log('in myCallback');
    console.dir(res);
    client.quit();
    process.exit();
  };
 async.concat(keys, client.hgetall, myCallback);
});
Salin selepas log masuk

错误还是和文章开头的一样,解决方法是使用bind 函数。修改倒数第二行代码如下:

async.concat(keys, client.hgetall.bind(client), myCallback);
Salin selepas log masuk

bind函数可以用来设置this 参数,具体用法看这里。

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan