2

任意のユーザーまたは別のユーザーがクリックすると更新されるグローバル ボタン カウンターを実装しようとしています。そのため、1 人がボタンをクリックすると、ページのインスタンスでカウンターが更新されます。

私は現在、ロング ポーリング テクニックが機能していると思いますが、レビューの結果、更新をすべてのブラウザーに「ブロードキャスト」することにエラーがあると思います。

現在のエラーは、たとえば 2 つのブラウザーを開いていて、1 つのブラウザーを継続的にクリックすると、ボタンをクリックしたブラウザーは半分の時間しか更新されないということです。他のブラウザが 2 4 6 などを表示している間、1 3 5 などを取得します。

オンラインでレビューした後、これはサイト上のすべてのブラウザへのチャネルとブロードキャストに関係していると思います. 毎回、すべてのブラウザにアップデートを送信する方法の例を教えてくれる人がいれば、本当に感謝しています。

クライアント:

<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 + "\n";
}
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>

サーバ:

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)
    }
}
4

2 に答える 2

8

問題は Go コード (単独; PS PS を参照) ではなく、ブラウザー (Chrome) です。同じ URL への 2 つのリクエストは、並行ではなく順番に行われます。

ソリューション ブラウザをだますために、一意のタイムスタンプを longpoll URL に追加する必要があります。

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

PS - この質問で Go チャネルとミューテックスについて多くのことを学びました。ありがとう :)

PS PS - James の回答 ( https://stackoverflow.com/a/19803051/143225 ) は、サーバー側の Go コードで一度に複数のリクエストを処理するための鍵です。これは、Go チャネルがブロックされているため、1 つのゴルーチンのみを意味するためです。一度に受け取ることができます。したがって、OP の質問に対する解決策は、フロントエンドとバックエンドのコード変更を組み合わせることです。

于 2013-11-06T07:00:22.583 に答える