【问题标题】:how to optimize jquery ajax chat?如何优化 jquery ajax 聊天?
【发布时间】:2019-01-16 08:26:42
【问题描述】:

我正在尝试构建我自己的 jquery ajax 聊天,它是当消息像 facebook 一样时的实时通知。计划是每 5 秒调用一次 ajax 请求,最后我的计划按我的预期运行良好。 但是在发送消息超过 5 次后,我的应用程序性能出现问题。当用户在输入框中输入消息时,浏览器变得很慢。 至少我在做以下方式:

//function to updating html element when new message comes (DOM operation)
function refresh_messanger(){

                $(".dialogdiv").remove();
                var y=get_update_message_in_messanger();

                for(var i=0; i<= y.length-1; i++){
                var message=y[i].message_content;
                var message_date=y[i].message_date;
                var src="";
                if(y[i].photo_profile=='{{session("session_photo_profile")}}'){
                    src="{{url('uploads/image').'/'.session('session_login')['app_user_id'].'/'.session('session_photo_profile')}}";
                }else{
                    src="{{url('uploads/image')}}/"+y[i].message_from+'/'+y[i].photo_profile;
                }
                var message_class="";
                if(i==0){
                    message_class="text-bold"
                }else{
                    message_class="text";
                }
                var messagehtml=['<div class="itemdiv dialogdiv">',
                            '<div class="user">',
                                '<img alt="" height="60" width="40" src="'+src+'">',                                
                            '</div>',
                            '<div class="body">',
                                '<div class="time">',
                                    '<i class="ace-icon fa fa-clock-o"></i>',
                                    '<span class="blue">'+message_date+'</span>',
                                '</div>',

                                '<div class="name">',
                                    '<a href="#"></a>',
                                '</div>',
                                '<div class="'+message_class+'">'+message+'</div>',
                                '<div class="tools">',
                                    '<a href="#" class="btn btn-minier btn-info">',
                                        '<i class="icon-only ace-icon fa fa-trash"></i>',
                                    '</a>',
                                '</div>',
                            '</div>',
                        '</div>'].join('\n');
                        //alert(messagehtml);
                        $("#message_wall").append(messagehtml);     
                }

            }

  //display number of messsage realtime
            function get_all_notif_message(){
                var number_of_messages=0;
                var message_from   ="{{$message_from}}";
                var message_to     ="{{$message_to}}";
                var message_url    ="{{url('messanger/realtime/message_notification')}}"+"/"+message_from+"/"+message_to;
                $.ajax({
                    url        :message_url,
                    contentType:"application/json",
                    type       :"get",
                    async      :false,
                    success: function (response) {
                      var data=JSON.parse(response);
                      //$("#total_message").val(data.number_of_messages)
                      //alert(data.number_of_messages)
                      number_of_messages=data.number_of_messages;
                    },
                    error: function(jqXHR, textStatus, errorThrown) {
                       console.log(textStatus, errorThrown);
                    }


                });
                return number_of_messages;
            }

//function to handle DOM operatioin base on old number total  
function listen_crud(){                 
  var uptodate_message=get_all_notif_message();         
  $("#uptodate_massage").val(get_all_notif_message());          
  if($("#total_message").val() < uptodate_message){
  //alert("new message received")
`var audio = new Audio('{{url("assets/sound/inquisitiveness.mp3")}}');              
audio.play();           
$("#total_message").val(uptodate_message);              
refresh_messanger();
`var objDiv =` `document.getElementById("message_container");`                              
objDiv.scrollTo(x-coord, y-coord);                      
 }      
} 
//first program running
setInterval(listen_crud,5000);

https://pastebin.com/6rhpwCir HTML View related to .dialogdiv class"

请给我你的建议。

【问题讨论】:

  • 我的建议是您在函数“get_all_notif_message”中的 ajax 请求不是同步的。正如您所做的那样,您的代码正在等待响应。您应该将更新信使的代码放在 ajax 调用的响应函数中,或者使用承诺。我认为你的表现会更好
  • 完全同意班德罗。您应该永远使用async: false,除非您真的不喜欢使用您的应用程序的人。但在这种情况下,您可能需要考虑使用WebSockets。这样一来,如果有新消息可用,您的服务器会通知浏览器,因此您不必等待 5 秒才能收到消息。
  • @Alimin 确实不能。但是您应该调用另一个函数来处理来自成功回调的响应。
  • @Alimin 您应该重新编写代码以允许 WebSockets,但您可以保留大部分代码。我不太了解 Laravel,但似乎 it supports WebSockets as well
  • @Alimin 是的,你应该把它放在 AJAX 成功中,但你也可以把它放在一个单独的函数中,然后从你的成功中调用该函数。

标签: jquery ajax performance


【解决方案1】:

@Alimin 设置async: false 会导致它BLOCK 输入/输出。这意味着在执行 ajax 期间,整个浏览器将不得不冻结,直到它作为响应返回,无论是成功还是错误。您说您不想在成功函数中做所有事情 - 这只是构建代码。 $.ajax() 返回一个承诺。您可以使用async/ await 并像同步代码一样编写它 - 更简洁时尚。

说实话,它的糟糕设计每隔几秒就调用一次 ajax 以实现“实时”。你可以做的是使用 websockets。套接字 IO 就是一个例子。它真的很简单而且很轻。你可以启动一个 Node 服务器来运行 Socket IO,并单独拥有你的 Laravel 服务器。

就这么简单:

客户端 Js - 在 Laravel 中

<script src="/socket.io/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script>
  $(function () {
    var socket = io('localhost:3000'); // connect to socket io server
    $('form').submit(function(e){
      e.preventDefault(); // prevents page reloading
      socket.emit('chat message', $('#m').val()); //replace with your msg input
      $('#m').val(''); //replace with your msg input
      return false;
    });

    socket.on('chat message', function(msg){
      console.log(msg); //receive message from node js
     });

  });
</script>

节点Js

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

app.get('/', function(req, res){
  res.sendFile(__dirname + '/index.html');
});

io.on('connection', function(socket){
  console.log('a user connected');
});

http.listen(3000, function(){
  console.log('listening on *:3000');
});

io.on('connection', function(socket){
  socket.on('chat message', function(msg){ //listen for 'chat message' event
    io.emit('chat message', msg); //send data to clients
    console.log('message: ' + msg);
  });
});

2019 年 17 月 1 日更新:

我已删除 async: false,因此浏览器无法保存。因此,要使用从 ajax 请求返回的数据,请使用 async/ await。它更整洁。

//function to updating html element when new message comes (DOM operation)
function refresh_messanger(){

$(".dialogdiv").remove();
    var y=get_update_message_in_messanger();

    for(var i=0; i<= y.length-1; i++){
        var message=y[i].message_content;
        var message_date=y[i].message_date;
        var src="";
        if(y[i].photo_profile=='{{session("session_photo_profile")}}'){
            src="{{url('uploads/image').'/'.session('session_login')['app_user_id'].'/'.session('session_photo_profile')}}";
        }else{
            src="{{url('uploads/image')}}/"+y[i].message_from+'/'+y[i].photo_profile;
        }
        var message_class="";
        if(i==0){
            message_class="text-bold"
        }else{
            message_class="text";
        }
        var messagehtml=['<div class="itemdiv dialogdiv">',
                    '<div class="user">',
                        '<img alt="" height="60" width="40" src="'+src+'">',                                
                    '</div>',
                    '<div class="body">',
                        '<div class="time">',
                            '<i class="ace-icon fa fa-clock-o"></i>',
                            '<span class="blue">'+message_date+'</span>',
                        '</div>',

                        '<div class="name">',
                            '<a href="#"></a>',
                        '</div>',
                        '<div class="'+message_class+'">'+message+'</div>',
                        '<div class="tools">',
                            '<a href="#" class="btn btn-minier btn-info">',
                                '<i class="icon-only ace-icon fa fa-trash"></i>',
                            '</a>',
                        '</div>',
                    '</div>',
                '</div>'].join('\n');
                //alert(messagehtml);
                $("#message_wall").append(messagehtml);     
    }

}

    //display number of messsage realtime
    async function get_all_notif_message(){
        var number_of_messages=0;
        var message_from   ="{{$message_from}}";
        var message_to     ="{{$message_to}}";
        var message_url    ="{{url('messanger/realtime/message_notification')}}"+"/"+message_from+"/"+message_to;

        let ajax_res;

        ajax_res = await $.ajax({
            url        :message_url,
            contentType:"application/json",
            type       :"get",    
        });

        let data = JSON.parse(ajax_res);
        return data.number_of_messages;
    }

    //function to handle DOM operatioin base on old number total  
    async function listen_crud(){ 
        let uptodate_message;


        try {
            uptodate_message= await get_all_notif_message();    
        } catch (error) {
            alert("Error");
            console.log(error);
            return;
        }                

        $("#uptodate_massage").val(uptodate_message);
        if($("#total_message").val() < uptodate_message){
            //alert("new message received")
            var audio = new Audio('{{url("assets/sound/inquisitiveness.mp3")}}');              
            audio.play();           
            $("#total_message").val(uptodate_message);              
            refresh_messanger();
            var objDiv = document.getElementById("message_container");                              
            objDiv.scrollTo(x-coord, y-coord);                      
        }      

        setTimeout(listen_crud, 5000);

    } 


    //first program running
    setTimeout(listen_crud, 5000);

资源:

https://socket.io/get-started/chat/

https://javascript.info/async-await

【讨论】:

  • 所以我需要什么要求。做你的技术?这足以添加 2 行并开始使用 socket IO.js 并使用 socket.io.js 进行简单的实际应用吗?
  • @Alimin Harus 下载 Node js dulu 兄弟。 Terus bikin 节点服务器,安装 express dan socket io。 lalu di client JS laravel,包含脚本客户端socket io nya:cdnjs.com/libraries/socket.io
  • 好的,谢谢,但我想我只需要在我的算法上实时优化我的 jquery。不要从头开始构建编码基础。我的项目使用 laravel 布局,我几乎完成了它们。
  • 问题是发送 5 条或更多消息后,应用程序变慢,浏览器也变慢。请仔细阅读我的帖子描述以了解整个问题
  • 好的。我去看看。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-01
  • 2013-08-29
  • 2013-11-01
相关资源
最近更新 更多