Skip to content

长轮询和短轮询 #9

Open
Open
@andyChenAn

Description

@andyChenAn

长轮询和短轮询

短轮询

短轮询:指的是客户端发起一个请求,服务器无论是否有新数据,都立即返回(有就返回新数据,没有就返回一个表示数据为空的响应),然后http连接断开。

setInterval(function () {
    $.ajax('/user' , funciton (data) {
        console.log(data);
    })
} , 1000)

上面的代码就是每隔1秒钟向服务器发送一次请求,服务器返回数据,客户端再对数据进行处理。这里有一个问题需要注意,如果当前网络比较慢时,服务器从接受请求,返回数据到客户端接受请求的总时间有可能会超过1秒,而请求是每隔1秒发送一次,这样会导致接收的数据到达先后顺序与发送顺序不一致。于是我们可以采用setTimeout的方式来进行轮询,来避免这样的情况发生。

function poll () {
    setTimeout(function () {
        $.ajax('/user' , function (data) {
            console.log(data);
            poll();
        })
    } , 1000)
}
poll();

长轮询

长轮询:指的是由客户端发起请求,如果服务器没有相关数据,那么服务器会hold住请求,直到服务器有相关数据,或等待一定时间超时才会返回。返回后,客户端又会发起请求。这个是需要客户端和服务器两者共同来完成的,我们来简单实现一个:

客户端代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<h1>hello world</h1>
<button id="btn">获取用户信息</button>
<script>
    var btn = document.getElementById('btn');
    btn.addEventListener('click' , (e) => {
        sendXhr();
    });
    function sendXhr () {
        var xhr = new XMLHttpRequest();
        xhr.open('get' , '/user');
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4) {
                if (xhr.status == 200) {
                    var result = JSON.parse(xhr.responseText);
                    // 如果服务器没有数据,那么会再一次发起请求
                    if (!result['result']) {
                        sendXhr();
                    } else {
                        console.log('有数据了');
                        console.log(result);
                    }
                } else {
                    console.log('失败');
                }
            }
        };
        xhr.send(null);
    }
</script>
</body>
</html>

服务端代码:

const express = require('express');
const app = express();
app.set('view engine' , 'html');
app.engine('html' , require('ejs').renderFile);
app.set('views' , './views');
app.use('/public' , express.static('static'));

app.get('/' , (req , res) => {
    res.render('./index.html');
});
app.get('/user' , (req , res) => {
    function sleep(count) {
        function inner () {
            let timer = setTimeout(function () {
                if (count == 1) {
                    clearTimeout(timer);
                    return res.status(200).json({result : ''});
                } else {
                    count--;
                    inner();
                }
            } , 1000)
        };
        inner();
    };
    sleep(5);
});
app.listen(3000 , () => {
    console.log('listening port on 3000');
})

就简单实现了一下,通过上面代码可知,当在客户端点击按钮时,会向服务器发送请求,而服务器上的代码,则会hold住请求5秒,然后再将数据发送给客户端,当客户端判断数据为空的时候,又重新向服务器发送请求。长轮询就是这样的一个过程。

心跳机制

心跳机制:指的是客户端每隔N秒向服务器发送一个心跳消息,服务器收到客户端的心跳小心后,回复同样的心跳消息给客户端,如果服务器或客户端再M秒(M>N)内没有收到心跳消息在内的任何消息,即心跳超时,那么我们就认为该连接已经断开了。

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions