React + Sails + Socket.io

Posted

技术标签:

【中文标题】React + Sails + Socket.io【英文标题】: 【发布时间】:2017-01-16 20:58:12 【问题描述】:

这是一个相当广泛的问题,但是我目前有一个 Sails API 服务器和一个 React 前端(独立)。

注意:React 前端不是 Sails 的一部分

我正在尝试掌握套接字,所以我想我会从简单的开始。我想实现以下目标:

用户访问我的网站 (React) React 打开一个套接字并连接到 Sails Sails 从函数/模型中流式传输数据 将新数据添加到模型时响应更新

我半理解使用 Express 和 React 是如何工作的,但是我无法理解 Sails 如何在 Sockets.io 之上实现他们的 WebSockets 版本。

我所做的是在 React 中安装 sockets.io-client,然后尝试在 Sails 中使用sails.sockets。

这是我目前拥有的:

React 组件 注意:我认为这根本不正确

componentDidMount =()=> 
  this.getSessionData();
  UserStore.listen(this.getSessionData);
  Socket.emit('/listSessions', function(data)
    console.log(data);
  )

Sails 函数 (listSessions)

listSessions: function(req, res) 
    Session.find( where: visible: true,  sort: 'createdAt DESC',
    function(err, sessions)

        if(req.isSocket)
            Session.watch(req.socket);
            console.log('User subscribed to ' + req.socket.id);
        

        if(err) return res.json(500, 
            error: err,
            message: 'Something went wrong when finding trades'
        );

        return res.json(200, 
            sessions: sessions,
        );
    )
,

Sails Function(createSession)在上面的函数中尝试使用publishCreate与Session.watch配合使用

createSession: function(req, res)

    var token = jwt.sign(
        expiresIn: 30,
    , 'overwatch');


    Session.create(
        username: req.body.username,
        platform: req.body.platform,
        lookingFor: req.body.lookingFor,
        microphone: req.body.microphone,
        gameMode: req.body.gameMode,
        comments: req.body.comments,
        avatar: null,
        level: null,
        hash: token,
        competitiveRank: null,
        region: req.body.region,
        visible: true,
    ).exec(function(err, created)

        Session.publishCreate(created);

        if(err) 
            console.log(err);
            return res.send(
                error: err,
                message: 'Something went wrong when adding a session',
                code: 91
            )
        
        if(req.isSocket)
            Session.watch(req.socket);
            console.log('User subscribed to ' + req.socket.id);
        
        return res.send(
            session: created,
            code: 00,
        )
    );
,

这两个 Sails 函数都是使用 POST/GET 调用的。 我完全不知道该去哪里,而且关于如何使其工作的文档或解释似乎是有限的。所有关于 Sockets 的 Sails 文档似乎都与使用 Sails 作为前端和服务器有关

【问题讨论】:

我以后可能会给出一个更充实的答案,但你很容易发现混淆。在您的客户端中,您将回调函数传递给socket.emit。这是不正确的。当您 EMIT 时,您传递数据(或 null 或其他)。当你想接收数据时,它是一个 ON 处理程序socket.on('someServerEvent', function (data) ... 谢谢,但是我想做的是在 Sails 的 listSession 函数上执行帖子 好吧,那不是这样的。尽管sails 可能包含一些内置的socket 东西给你,但没有什么能阻止你添加socket.io 服务器端包并在那里监听事件,传递你需要的任何模型数据。套接字是基于命名事件的事件,这些事件不同于用于 HTTP 调用的路由。 是的,我认为这不是它的工作原理,但是我什至无法弄清楚如何让 Sails 函数将数据发送到连接。根据文档,publishCreate 和 Watch 一起工作,但正如您在我的代码中看到的,我需要先将初始数据获取到 React 【参考方案1】:

好的,所以我设法解决了这个问题:

简单地说:

在 React 中,我必须包含 https://github.com/balderdashy/sails.io.js/tree/master

然后在我的 React 组件中我做了:

  componentDidMount =()=> 
    io.socket.get('/listSessions',(resData, jwres) => 
      console.log('test');
      this.setState(
        sessions: resData.sessions,
        loaded: true,
      )
    )

    io.socket.on('session', (event) => 
      if(event.verb == 'created') 

        let sessions = this.state.sessions;
        sessions.push(event.data);
        this.setState(
          sessions: sessions
        )
       else 
        console.log('nah');
      
    );
  

这会使用 Socket.io 向 Sails 发出虚拟获取请求,并将响应设置为状态。它还监视“会话”连接的更新并使用这些更新更新状态,这意味着我可以实时更新列表

在我的 Sails 控制器中,我有:

listSessions: function(req, res) 

    if(req.isSocket)
        Session.find( where: visible: true,  sort: 'createdAt DESC',
        function(err, sessions)

            Session.watch(req.socket);

            if(err) return res.json(500, 
                error: err,
                message: 'Something went wrong when finding trades'
            );

            return res.json(200, 
                sessions: sessions,
            );
        )
    
,

Session.watch 行通过 publishCreate 在我的模型中找到的模型上侦听更新,如下所示:

  afterCreate: function(message, next) 
    Session.publishCreate(message);
     next();
   ,

【讨论】:

你是如何整合风帆和反应的?你知道任何文学作品吗?【参考方案2】:

添加@K20GH 的回答,将以下内容添加到我在 React 中的“index.js”中,以帮助从 CDN 获取sails.io.js:

const fetchJsFromCDN = (src, externals = []) => 
return new Promise((resolve, reject) => 
    const script = document.createElement('script');
    script.setAttribute('src', src);
    script.addEventListener('load', () => 
        resolve(
            externals.map(key => 
                const ext = window[key];
                typeof ext === 'undefined' &&
                    console.warn(`No external named '$key' in window`);
                return ext;
            )
        );
    );
    script.addEventListener('error', reject);
    document.body.appendChild(script);
);
;
fetchJsFromCDN(
    'https://cdnjs.cloudflare.com/ajax/libs/sails.io.js/1.0.1/sails.io.min.js',
    ['io']
).then(([io]) => 
    if (process.env.NODE_ENV === 'development') 
        io.sails.url = 'http://localhost:1337';
    
);

一旦你有了这个,你就可以使用 HTTP 类型的 GET、PUT、POST 和 DELETE 方法。所以在这里你可以这样做:

componentDidMount =()=> 
io.socket.get('/listSessions',(resData, jwres) => 
  console.log('test');
  this.setState(
    sessions: resData.sessions,
    loaded: true,
  )
)

io.socket.on('session', (event) => 
  if(event.verb == 'created') 

    let sessions = this.state.sessions;
    sessions.push(event.data);
    this.setState(
      sessions: sessions
    )
   else 
    console.log('Not created session');
  
);

您可以按照上面的建议在sails 中为会话模型进行所需的设置

【讨论】:

以上是关于React + Sails + Socket.io的主要内容,如果未能解决你的问题,请参考以下文章

跨域 Sails.js + Socket.io 授权

将socket.io与sails js一起使用

如何在 Python 中创建 Socket.io 客户端以与 Sails 服务器通信

Sails.js 与本机 WebSockets

sails.io.js - nodejs - 资源丰富的 PubSub 未接收模型事件

使用 Socket.IO 和 NodeJS 实现音频聊天