dongmi1864 2013-11-06 00:51
浏览 70
已采纳

长轮询,“全局”按钮,向所有人广播?

I am trying to implement a global button counter that updates as any/different users click it. So the idea is if one person clicks the button, I see the counter update on my instance of the page.

I currently have the long polling technique working, or so I think, but after review I believe I have an error with "broadcasting" the update to all browsers.

The error currently is that if for example I have two browsers open, and I continuously click on one browser, that browser that I click the button only updates half the time. It will get 1 3 5 etc while the other browser displays 2 4 6 etc.

After reviewing online, I think this may have to do with channels and broadcasting to all those browsers that are on the site. If anyone can help me with an example of how I might send the update to all browsers, every time, I'd really appreciate it.

Client:

<html>
<script language=javascript>

function longpoll(url, callback) {

    var req = new XMLHttpRequest (); 
    req.open ('GET', url, true); 

    req.onreadystatechange = function (aEvt) {
        if (req.readyState == 4) { 
            if (req.status == 200) {
                callback(req.responseText);
                longpoll(url, callback);
            } else {
                alert ("long-poll connection lost");
            }
        }
    };

    req.send(null);
}

function recv(msg) {

    var box = document.getElementById("counter");

    box.innerHTML += msg + "
";
}
function send() {


    var box = document.getElementById("counter");

  var req = new XMLHttpRequest (); 
    req.open ('POST', "/push?rcpt=", true); 

    req.onreadystatechange = function (aEvt) {
        if (req.readyState == 4) { 
            if (req.status == 200) {
            } else {
                alert ("failed to send!");
            }
        }
  };
  req.send("hi")

  //box.innerHTML += "test" ;  
}
</script>
<body onload="longpoll('/poll', recv);">

<h1> Long-Poll Chat Demo </h1>

<p id="counter"></p>
<button onclick="send()" id="test">Test Button</button>
</body>
</html>

Server:

package main

import (
    "net/http"
    "log"
    "io"
//  "io/ioutil"
  "strconv"
)

var messages chan string = make(chan string, 100)

var counter = 0

func PushHandler(w http.ResponseWriter, req *http.Request) {

    //body, err := ioutil.ReadAll(req.Body)

    /*if err != nil {
        w.WriteHeader(400)
    }*/
    counter += 1
    messages <- strconv.Itoa(counter)
}


func PollResponse(w http.ResponseWriter, req *http.Request) {

    io.WriteString(w, <-messages)
}

func main() {
    http.Handle("/", http.FileServer(http.Dir("./")))
    http.HandleFunc("/poll", PollResponse)
    http.HandleFunc("/push", PushHandler)
    err := http.ListenAndServe(":8010", nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}
  • 写回答

2条回答 默认 最新

  • dse55384 2013-11-06 07:00
    关注

    The issue isn't the Go code(alone;see PS PS), it's the browser(Chrome). Making 2 requests to the same URL happens in sequence, not in parallel.

    Solution You need to add a unique timestamp to the longpoll URL to trick the browser:

    req.open ('GET', url+"?"+(new Date().getTime()), true); 
    

    PS - I learned a lot about Go channels and mutex with this question. Thanks :)

    PS PS - James' answer (https://stackoverflow.com/a/19803051/143225) is key to getting the server side Go code to handle more than 1 request at a time, because Go channels are blocking which means only 1 goroutine can receive at a time. So the solution to the OP's question is a combination of front and back end code changes.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 逻辑谓词和消解原理的运用
  • ¥15 三菱伺服电机按启动按钮有使能但不动作
  • ¥15 js,页面2返回页面1时定位进入的设备
  • ¥200 关于#c++#的问题,请各位专家解答!网站的邀请码
  • ¥50 导入文件到网吧的电脑并且在重启之后不会被恢复
  • ¥15 (希望可以解决问题)ma和mb文件无法正常打开,打开后是空白,但是有正常内存占用,但可以在打开Maya应用程序后打开场景ma和mb格式。
  • ¥20 ML307A在使用AT命令连接EMQX平台的MQTT时被拒绝
  • ¥20 腾讯企业邮箱邮件可以恢复么
  • ¥15 有人知道怎么将自己的迁移策略布到edgecloudsim上使用吗?
  • ¥15 错误 LNK2001 无法解析的外部符号