使用GraphQL Apollo跟踪在线用户

时间:2018-01-19 09:52:58

标签: node.js websocket graphql apollo apollo-server

我需要在GraphQL Apollo Node.js服务器上处理“用户现在在线”和“用户现在离线”的事件。最好的方法是什么?

我的调查:我非常确定我不需要实现任何心跳逻辑,因为订阅正在处理WebSockets。但我没有在他们的文档中找到任何信息如何处理WebSockets事件,如“连接”和“断开”订阅...实际上我可以从实际订阅的外部处理这些事件:

SubscriptionServer.create({
    execute,
    subscribe,
    schema,
    onConnect = (...args) => {
        console.log('User connected')
    },
    onDisconnect = (...args) => {
        console.log('User disconnected')
    }
}, {
    server: ws,
    path: '/subscriptions'
})

但无法确定通过此套接字连接了哪个用户。

我的实施:现在我的工作就是这样:

  1. 我们为所有调用都表达了中间件,它将用户对象从jsonwebtoken推送到req对象。在这里,我可以触发“用户现在在线”逻辑。

  2. 我创建了单独的订阅,客户端在登录时订阅它并取消订阅注销。由于没有取消订阅处理程序,我设法确定在没有负载的情况下在用户断开连接时调用过滤器函数,所以我采用了这种方法:

    userOnlineSubscription: {
        subscribe: withFilter(
            () => pubSub.asyncIterator('userOnlineSubscription'),
                async (payload, variables) => {
                    if (!payload) {
                        // set user offline
                }
                return false
            }
        )
    }
    
  3. 至于我,上面的解决方案很难看。有人可以推荐更好的方法吗?

1 个答案:

答案 0 :(得分:1)

我使用了这种方法

onConnect (connectionParams, webSocket) {
  const userPromise = new Promise((resolve, reject) => {
    if (connectionParams.jwt) {
      jsonwebtoken.verify(
        connectionParams.jwt,
        JWT_SECRET,
        (err, decoded) => {
          if (err) {
            reject(new Error('Invalid Token'))
          }

          resolve(
            User.findOne({
              where: { id: decoded.id }
            })
          )
        }
      )
    } else {
      reject(new Error('No Token'))
    }
  })

  return userPromise.then(user => {
    if (user) {
      return { user: Promise.resolve(user) }
    }

    return Promise.reject(new Error('No User'))
  })
}