Jordan,
Thank you, that's good advice. I've looked at jQuery and think it looks
really neat, and I'd probably use it in a real-world project. For my Life
game, this is, as I said in another thread, the most sophisticated web
programming I've done, and I wanted to do it "the hard way", on the theory
that by writing it myself I'd get a better understanding of some of the
issues involved.
The route I've decided to take, at least for the moment, is to keep a list
of all listeners, and not to care if any given connection is open or not.
Every event for a particular session goes back to every listener, so of
one of those listeners has closed the connection, the goroutine gets
cleaned up, and for any that are still alive, they all get the event. If
you press reload, or open a new window, I push an empty event back to all
listeners, and so again any dead connections (and their associated
goroutines) will thus just go away essentially on their own.
Thanks again for your response, and for doing me the honor of looking at my
code! :)
-- Larry
On Tuesday, September 18, 2012 2:22:29 PM UTC-4, jorelli wrote:another potential solution, instead of worrying about connection
hijacking, is to add some kind of progress parameter to your polling call,
generally a timestamp or incremental ID. Since you're writing Conway's
game of life, you probably want to number your generations and have the
client send the generation number that it has last recorded, and have the
server serve the following generation (or generations).
looking at your repository, I strongly recommend using jQuery over doing
the XMLHttpRequest boilerplate by hand. They've got all that cross-browser
boilerplate figured out, and the API is much nicer.
I have a long-polling chatroom app that uses jQuery here, if you want to
use it for reference:
https://github.com/jordanorelli/gochatbut it's really old and it's one of the first things I wrote in Go; I
think it has the same problem you're describing, so I can't honestly say
it's of good quality. I don't know that I've even run it since Go1 came
out. But it's longpolling between javascript and Go, using jQuery,
nonetheless.
best of luck on your project
-jordan
On Saturday, September 15, 2012 8:09:24 PM UTC-4, Larry Clapp wrote:I've been doing some Ajax-y stuff with Go, and have run into a problem.
I have buttons in life.html that send events via GET
"/button?title=button_id", and the response comes back via a "long poll<
http://en.wikipedia.org/wiki/Push_technology#Long_polling>"
XMLHttpRequest to GET "/updates". "/button" goes to Button(); "/updates"
goes to Updates(). Button() puts the response on a channel; Updates()
listens on the channel and sends it back as the response to the long poll.
So my problem is that when I hit "reload" on the main webpage, the "long
poll" of /updates is closed, and a new one is opened. But Updates()
doesn't realize this, and continues to wait on its channel. When you press
a button, and input does finally come in on the channel, Updates() sends it
out on the ResponseWriter, but it's the wrong ResponseWriter, it's the one
from before you pressed reload. So if you press reload once, the first
button press is ignored; if you press reload N times, the first N button
presses are ignored, eaten by the first N Updates() goroutines.
So my question is two-fold: Am I doing this Ajax-y thing entirely wrong?
And if not, how can I tell, in Updates(), that the connection has been
closed and I shouldn't try to write the response to the button-press on it?
Now, I realize that ideally I would keep track of what connection is
active, and send the response to the active query. Even in that case, I'd
still somehow like to be able to close down the Updates() goroutine(s)
that's now inactive; otherwise each reload would leak a goroutine.
The full repository is here:
https://github.com/theclapp/go-life .
Thank you for your help!
-- Larry
--