每秒更新来自 api 的消息

Posted

技术标签:

【中文标题】每秒更新来自 api 的消息【英文标题】:Update messages from api every second 【发布时间】:2019-04-11 01:50:23 【问题描述】:

我在我的 react 原生移动应用程序中使用react-native gifted-chat 作为我的聊天界面,在我的组件中,我将从一个 api 获取用户的消息并将其呈现在有天赋的聊天界面中,在有天赋的聊天中发送的任何消息也被发送到一个api,它将消息保存在db中。现在我想每秒更新一次消息状态,以便当其他用户也向它更新的当前用户发送消息时,我尝试使用设置间隔但模拟器总是挂起,请问更新消息的最有效方法是什么除了我所做的以外的数组

 constructor(props) 
    super(props);
    this.state = 
        messages: []
    ;
    this.checker = this.checker.bind(this);
;
checker()
    const params = this.props.navigation.state;
           this.setState(loading: true);
           var bodyParameters = 
               id: params.id,
               receiver_id: params.receiver_id
           
          /*    var config = 
               headers: 'Authorization': "Bearer " + this.state.token
          ;*/
          axios.post(
              'http://10.0.2.2:8000/api/messages',
              bodyParameters,
          //      config
          ).then((response) => 
           this.setState(loading: false);
           console.log(response);   
           var len = response.data.success?response.data.success.length:null;
           for (let i = 0; i < len; i++) 
               let row = response.data.success[i];
               console.log(row.id, row.user1.id);console.log("chat")
               this.setState(prevState => (
                   messages: [...prevState.messages, _id: row.id, text: row.message, 
                       createdAt: row.created_at, user: _id: row.user1.id,name: row.user1.first_name+' '+row.user1.last_name],
               ), console.log(this.state.messages));
               console.log("checker");
           ;
          ).catch((error) => 
           this.setState(loading: false); 
                   console.log(error); 
                  );      

componentDidMount()
this.interval = setInterval(() => this.checker(), 1000);

componentWillUnmount() 
        clearInterval(this.interval);
      
componentWillMount() 
    const params = this.props.navigation.state;
 /*   var pusher = new Pusher('1363556f717d953dcf86', 
        cluster: 'mt1',
        forceTLS: true
      );
      var channel = pusher.subscribe('private-messages.'+ params.id);
      channel.bind('MessageSent', function(data) 
        console.log(data);
      );*/
        this.setState(loading: true);
        var bodyParameters = 
            id: params.id,
            receiver_id: params.receiver_id
        
    /*    var config = 
            headers: 'Authorization': "Bearer " + this.state.token
       ;*/
       axios.post(
           'http://10.0.2.2:8000/api/messages',
           bodyParameters,
     //      config
       ).then((response) => 
        this.setState(loading: false);
        console.log(response);   
        var len = response.data.success?response.data.success.length:null;
        for (let i = 0; i < len; i++) 
            let row = response.data.success[i];
            console.log(row.id, row.user1.id);console.log("chat")
            this.setState(prevState => (
                messages: [...prevState.messages, _id: row.id, text: row.message, 
                    createdAt: row.created_at, user: _id: row.user1.id,name: row.user1.first_name+' '+row.user1.last_name],
            ), console.log(this.state.messages));
            console.log("contjii");
        ;
       ).catch((error) => 
        this.setState(loading: false);
            Alert.alert(
                'Error',
                 'Internal Server Error, please try again later',
                [
                  text: 'OK',
                ],  );    
                console.log(error); 
               );    
 /*   this.setState(
      messages: [
        
          _id: 1,
          text: 'Hello developer',
          createdAt: new Date(),
          user: 
            _id: 1,
            name: 'React Native',
            avatar: 'https://placeimg.com/140/140/any',
          ,
      //    image: 'https://facebook.github.io/react/img/logo_og.png',
          // additional custom parameters
          sent : true,
          received : true,
        ,
      ],
    )*/
  

  onSend(messages = []) 
      console.log(messages);
      const params = this.props.navigation.state;
      messages[0].sent = true;
    var bodyParameters = 
        id: params.id,
        receiver_id: params.receiver_id,
        message: messages[0].text
    
/*    var config = 
        headers: 'Authorization': "Bearer " + this.state.token
   ;*/
   axios.post(
       'http://10.0.2.2:8000/api/sendMessage',
       bodyParameters,
 //      config
   ).then((response) => 
    this.setState(loading: false);
    console.log(response);   

   ).catch((error) => 
    this.setState(loading: false);
        Alert.alert(
            'Error',
             'Internal Server Error, please try again later',
            [
              text: 'OK',
            ],  );    
            console.log(error); 
           ); 
      this.setState(previousState => (
      messages: GiftedChat.append(previousState.messages, messages),
    ));  
  
render() 
    const params = this.props.navigation.state;
    return (
<GiftedChat
        messages=this.state.messages
       //  inverted=false
        onSend=messages => this.onSend(messages)
        user=
          _id: params.id,
        
      />
 );
 

【问题讨论】:

【参考方案1】:

代码的问题在于 setInterval 不断发送 API 调用,而不关心之前的调用是否返回。 这在服务器上一次排队了很多请求。要解决此问题,您应该等待 API 响应,然后再进行下一次 API 调用。

【讨论】:

【参考方案2】:

处理此问题的最有效方法是使用 Web Sockets 协议,该协议会将通知从服务器发送到 UI 客户端。很难给你举个例子,因为我们不知道你的服务器堆栈,但是像 SignalR in.Net world 这样的东西在这里会很完美。

这里的前提是,服务器不会每秒向服务器询问新消息,而是会在有新消息时通知客户端。这样你会节省很多资源。

【讨论】:

我使用 Laravel 作为我的后端,我一次使用 pusher 作为我的 web socket,但是它限制了一天可以发送的消息,到目前为止我还没有找到一个 web socket是免费的,这就是为什么我想以老式的方式每秒更新消息 在我看来,Pusher 是一个服务而不是一个库。所以你发送一些数据给 Pusher,然后 Pusher 发送给你的客户端。我所说的是这样的:socketo.me 你可以配置你自己的 Laravel 服务器来使用这个库并向你的 UI 发送消息。不会有任何您需要支付的第三方参与。这是 Laravel 的广播文档:laravel.com/docs/5.7/broadcasting 你不需要使用 Pusher 来完成这项工作。 谢谢你,我会通读文档,然后我可能不得不切换到网络套接字

以上是关于每秒更新来自 api 的消息的主要内容,如果未能解决你的问题,请参考以下文章

每秒更新 ListView 处理程序不起作用

网站上的实时更新 - 每秒 1 个 ajax 是不好的做法?

提高 SQLite 的每秒更新性能?

如何区分“消息”更新和“回调查询”更新? (电报机器人 API)

使用 Asana API 更新任务时出现“请求没有匹配的路由”消息

如何在UI上更新记录后显示来自message.properties的消息