Redis NodeJs 服务器错误,客户端已关闭。

33

我正在开发一个应用程序,需要缓存和监控聊天记录,目前这是一个本地应用程序,在其中我安装了Redis和redis-cli。 我遇到的问题是(node:5368) UnhandledPromiseRejectionWarning: Error: The client is closed 下面附上代码片段

//redis setup
const redis = require('redis');
const client = redis.createClient()//kept blank so that default options are available
  

//runs when client connects
io.on("connect", function (socket) {

  //this is client side socket
  //console.log("a new user connected...");

  socket.on("join", function ({ name, room }, callback) {
    //console.log(name, room);
    const { msg, user } = addUser({ id: socket.id, name, room });
   // console.log(user);
    if (msg) return callback(msg); //accessible in frontend

    //emit to all users
    socket.emit("message", {
      user: "Admin",
      text: `Welcome to the room ${user.name}`,
    });
    //emit to all users except current one
  
    socket.broadcast
      .to(user.room)
      .emit("message", { user: "Admin", text: `${user.name} has joined` });

    socket.join(user.room); //pass the room that user wants to join

    //get all users in the room
    io.to(user.room).emit("roomData", {
      room: user.room,
      users: getUsersInRoom(user.room),
    });

    callback();
  }); //end of join

  //user generated messages
  socket.on("sendMessage",  async(message, callback)=>{
    const user = getUser(socket.id);

    //this is where we can store the messages in redis
    await client.set("messages",message);

    io.to(user.room).emit("message", { user: user.name, text: message });
    console.log(client.get('messages'));
    callback();
  }); //end of sendMessage

  //when user disconnects
  socket.on("disconnect", function () {
    const user = removeUser(socket.id);
    if (user) {
     
      console.log(client)

      io.to(user.room).emit("message", {
        user: "Admin",
        text: `${user.name} has left `,
      });
    }
  }); //end of disconnect

当用户发送一条消息到房间或调用socket.on("sendMessage")时,我收到了上述错误。

我错在哪里了?

提前感谢您。

9个回答

72

在使用客户端之前,应该await client.connect()


谢谢您的回答,@Leibale Eidelman :) - Makarand
这真的很有帮助!谢谢 - Sharky

41

在 node-redis V4 中,客户端不会自动连接到服务器,你需要在执行任何命令之前运行 .connect(),否则你将收到错误提示 ClientClosedError: The client is closed。

import { createClient } from 'redis';

const client = createClient();

await client.connect();

或者您可以使用传统模式来保留向后兼容性。

const client = createClient({
    legacyMode: true
});

22
您在异步函数之外调用了 await。 - hane Smitter
2
你可以像这样将其包装在异步方法中:(async () => { await client.connect(); })(); - Asad Fida

5

client.connect()返回一个Promise。因为你无法在函数外部调用await,所以必须使用.then()。

const client = createClient();  
client.connect().then(() => {
  ...
})

1
你的回答可以通过添加更多关于代码的信息以及它如何帮助提问者来改进。 - Tyler2P

5
我曾经遇到过类似的问题,然后我按照以下方式改变了连接代码。
const client = redis.createClient({
  legacyMode: true,
  PORT: 5001
})
client.connect().catch(console.error)

4

使用"redis": "3.1.2"版本。


为什么?请解释。 - Lin Du
https://github.com/redis/node-redis/issues/1780 - mesutpiskin
使用3.1.2版本解决了我的问题。我正在使用redis 3.2.12,我不能使用最新的npm包吗?@mesutpiskin - Amit Kumar

3

你不能在函数外调用 await。这是我自己做的方法。

const redis = require('redis');

const redisClient = redis.createClient()

redisClient.on('connect', () => {
    console.log('Connected to Redis12345');
})

redisClient.on('error', (err) => {
    console.log(err.message);
})

redisClient.on('ready', () => {
    console.log('Redis is ready');
})

redisClient.on('end', () => {
    console.log('Redis connection ended');
})

process.on('SIGINT', () => {
    redisClient.quit();
})

redisClient.connect().then(() => {
    console.log('Connected to Redis');
}).catch((err) => {
    console.log(err.message);
})

In app.js

//just for testing

const redisClient = require('./init_redis')

redisClient.SET('elon', 'musk', redisClient.print)

My data in redis


2

你不能在函数外部调用await。

const redis = require('redis');
const client = redis.createClient();

client
  .connect()
  .then(async (res) => {
    console.log('connected');
    // Write your own code here

    // Example
    const value = await client.lRange('data', 0, -1);
    console.log(value.length);
    console.log(value);
    client.quit();
  })
  .catch((err) => {
    console.log('err happened' + err);
  });

1

尝试了几个选项,但都不起作用。

按照mesutpiskin的建议使用redis 3.1.2进行了尝试。

这样做对我很有帮助。

对于连接redis 4.x.x存在复杂问题。

您可以从文档redis中的片段尝试。


1
可能会发生另一个实例正在使用该端口,因此它不允许我们使用相同的端口。您可以尝试使用新的端口,或者您可以使用以下命令进行检查:
netstat -ano | find "6379"
这将返回PID(进程ID)。
如果该端口上有一个进程,您可以使用以下命令终止它:
taskkill /F /PID 然后重新启动连接进程。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接