redis怎么同步调用get?
发布于 3 年前 作者 muzi-xiangxiang 7142 次浏览 来自 问答
var redis = require('redis');
var https = require("https");
var client = redis.createClient(6379, "127.0.0.1",{db:1});
//错误监听
client.on("error", function (err) {
  console.log("Error " + err);
});

var tt;
client.get('accessToken',function (d,r) {
  console.log(r);
return tt=r;
})
console.log(tt);//一直是undefined
exports.accessToken = tt;
exports.redis = redis;
exports.clients = client;

怎么让他同步执行赋值给tt,这样就不要每次都去获取accessToken了

23 回复
1.Async/Await
2.
exports.accessToken = function(cb){
	client.get('accessToken',function (d,r) {
		cb(d,r);
	})
}

@imhered 这样不行啊!调用怎么赋值给一个全局变量?

var client = require('./redisdb').accessToken;
console.log(client);//希望这里可以打印出数据

@muzi-xiangxiang 你需要去补补异步方面的知识。 如果想要完全实现同步形式的代码的话,只能用ES7 的Async/Await了(但它实际上也是异步的) 上面给你说的第二种方式 调用的时候应该这样

	var client = require('./redisdb').accessToken;
	client(function(e,r){
		// 这里的 r 就是 accessToken的值
	})

@imhered 我知道这样调用,其实我就是不想每次用到accessToken都在回调里面取值

var client = require('./redisdb').accessToken;
var cc;//全局变量
client(function(e,r){
  // 这里的 r 就是 accessToken的值
  cc=r;//赋值

})
get(cc,function(err,d){//调用是cc不再是undefined

})

@muzi-xiangxiang 如果你强行要同步调用,你可以使用一个包叫deasync,这个包可以把异步变同步,但代价非常大,大到了程序会偶发的hand up

其实楼主只是需要形式上(写法上)的同步而已

因为 redis.get 是一个异步的方法,需要实现同步,则需要阻塞主线程然后等待请求完成。这也就是为什么 deasync 这个包會导致程序 hand up 的原因。

建议楼主可以改下你实现的形式嘛,可以用 async/await 或者 event-emitter

强行同步毕竟与 js 的编程思维相悖啊。。。

强迫症分行。。。

使用sync-request同步了请求连redis都不需要了

var request = require('sync-request');
var res = request('GET', 'https://oapi.dingtalk.com/gettoken');
console.log(res.getBody('utf-8'));
var cc = JSON.parse(res.getBody('utf-8'));
console.log(cc.access_token);

优雅地使用promise

使用bluebird转换,官方都是这么推荐的

	bluebird.promisifyAll(redis.RedisClient.prototype);
	bluebird.promisifyAll(redis.Multi.prototype);
	
	var value = await client.getAsync(XXXX);

@Yuki-Minakami node8.1.13运行await报错,难道不支持吗? image.png

@muzi-xiangxiang 肯定支持的,看看是不是哪个变量没声明,还有await要跟async一块用

额,哥们你可能还没用过async/await

	async function test(){
		var value = await client.getAsync(XXXX);	
		console.log(value);
	}
	test()

@Yuki-Minakami 确实没用过…打印Promise { <pending> }不是value的值

test().then(function (d) {
  console.log(d);//这样样调用打印d就是value的值
  //但这却不是我想要的
})

@muzi-xiangxiang 不好意思刚才打错了,现在再试下楼上的代码 async返回值永远是个promise,直接调用test也拿不到返回值,要调用then才可以

@Yuki-Minakami 谢谢你 其实我就是想把value的值赋给一个全局变量,而不是打印出来但是异步让我无法得到他的值

解决思路,这是一个子进程,父进程把redis数据查询完并写入文件后再启动子线程,子线程同步读取文件获取redis查询的值,整体看来,完成了把异步查询的数据,获取到了子进程的全局变量

来自酷炫的 CNodeMD

client.get('accessToken',function (d,r) {
  console.log(r);
return tt=r;
})
//这样tt是永远undefined,因为是异步,程序跑还没有跑完client.get就会跳到console.log,所以tt永远是没有值
console.log(tt);//一直是undefined

另外根据我在公司里的经验,把异步和同步放在一起使用的设计是错误的,这样就会很容易出现你上面的问题,而且非常难debug 如果要想做成像同步,首先把callback函数变成promise,再利用async/await去处理

//这里会用到bluebird
const Bluebird = require('bluebird')
export.clientPromise = new Bluebird( (resolve, reject) => client
  .get('accessToken', (d, r) => {
     resolve(r)
  })
)

然后正如@Yuki-Minakami 所说

	async function test(){
		var token = await clientPromise()
		//然后test你的token。。。。
	}
	//这里的test()返回值还是promise,async的返回值永远都是promise
	test()

其实楼上也说得挺明白的,强行异步变同步 js 的编程思维相悖。

如果你非要同步,可以把accessToken写到json文档里然后用fs.readFileSync(文档地址)来获取token

要同步换语言,比如openresty。

node短时间内不太可能实现形式同步。

回到顶部