As per my understanding, the browser client is single threaded. How to
get the server to interrupt the browser client to say "stop"?
I modified Flanagan's example code here:
var HTTP = {
// This is a list of XMLHttpRequest creation factory functions to try
_factories : [
function() { return new XMLHttpRequest(); },
function() { return new ActiveXObject("Msxml2.XMLHTTP"); },
function() { return new ActiveXObject("Microsoft.XMLHTTP"); }
],
// When we find a factory that works, store it here
_factory : null,
// Create and return a new XMLHttpRequest object.
//
// The first time we're called, try the list of factory functions
until
// we find one that returns a nonnull value and does not throw an
// exception. Once we find a working factory, remember it for later
use.
//
newRequest : function() {
if (HTTP._factory != null) return HTTP._factory();
for(var i = 0; i < HTTP._factories.length; i++) {
try {
var factory = HTTP._factories[i];
var request = factory();
if (request != null) {
HTTP._factory = factory;
return request;
}
}
catch(e) {
continue;
}
}
// If we get here, none of the factory candidates succeeded,
// so throw an exception now and for all future calls.
HTTP._factory = function() {
throw new Error("XMLHttpRequest not supported");
}
HTTP._factory(); // Throw an error
},
/**
* Use XMLHttpRequest to fetch the contents of the specified URL
using
* an HTTP GET request. When the response arrives, pass it (as plain
* text) to the specified callback function.
*
* This function does not block and has no return value.
*/
toServer : function(url) {
var request = HTTP.newRequest();
request.onreadystatechange = function() {
if (request.readyState == 4 && request.status == 200)
MyProxy.fromServer(request.responseText);
}
request.open("GET", url, true); // 3rd param implies asynchronous
console.log("sending " + url);
request.send(null);
},
};
.....
// MyProxy
...
fromServer: function(command) {
console.log("fromServer: " + command);
eval(command);
},
thanks,
Anil
The communication has to be initiated by the client. Either keep
polling the server periodically[Ajax with polling] or use something
along the lines of Comet technology [Web Server push enabled by the
use of long held http connections].
<URL: http://en.wikipedia.org/wiki/Comet_(programming)>
/sasuke
Thanks for replying. I was wondering if a trick like this would work,
but it doesn't seem to. Is it a bug in my implementation or is it
conceptually faulty?
In MyProxy.fromServer(), issue another toServer("url").
Thus there will always be a GET request pending. Since it is
asynchronous, it will return immediately. But the callback will occur
while the client is executing.
so what happens here - what will the browser do - will it simply
block, or a new thread be created? My understanding is stuck here.
Javascript implementations don't support threading. When making asyn
requests, the browser never blocks; instead as soon as a response is
returned from the server, the callback function is executed which
performs the required processing.
Like I mentioned before, just keep polling the server for commands
using setInterval and make provision for a NO-OP command. Thoroughly
read the Comet article in case you want to avoid polling. Modern web
servers like Tomcat come with in-built Comet support.
/sasuke
That is correct, however it is rather irrelevant here because the point
in using asynchronous request-response handling (as you do) is to work
around that.
> How to get the server to interrupt the browser client to say "stop"?
One possibility is the obvious:
fromServer: function(command) {
console.log("fromServer: " + command);
if (command != "stop")
{
eval(command);
}
},
That is not interrupting anything, though, as nothing needs to be
interrupted in the first place.
However, the reference implementation and other implementations also support
a way to cancel the current HTTP request while it is in progress, the
abort() method:
<http://msdn.microsoft.com/en-us/library/ms760305(VS.85).aspx>
<https://developer.mozilla.org/En/XMLHttpRequest>
<http://www.opera.com/docs/specs/xhr/index.dml>
<http://developer.kde.org/documentation/library/3.4-api/khtml/html/xmlhttprequest_8cpp-source.html>
<http://trac.webkit.org/browser/branches/Safari-3-2-branch/WebCore/xml/XMLHttpRequest.cpp#L481>
> I modified Flanagan's example code here:
You should not use Flanagan's code, and particularly not this code as it is
error-prone.
PointedEars
--
Anyone who slaps a 'this page is best viewed with Browser X' label on
a Web page appears to be yearning for the bad old days, before the Web,
when you had very little chance of reading a document written on another
computer, another word processor, or another network. -- Tim Berners-Lee
Also, "stop" is not for canceling the http request. stop() does a
specific task.
thanks,
Anil
On Oct 22, 3:21 pm, Thomas 'PointedEars' Lahn <PointedE...@web.de>
wrote:
It uses exception handling without fallback to begin with.
> Is there better code that will do the same thing...
Yes.
> if so, can you please point me to it?
It is located in your /dev/brain.
Please don't top-post. Reply below parts of trimmed quotes instead.
PointedEars
--
realism: HTML 4.01 Strict
evangelism: XHTML 1.0 Strict
madness: XHTML 1.1 as application/xhtml+xml
-- Bjoern Hoehrmann
> As per my understanding, the browser client is single threaded. How to
> get the server to interrupt the browser client to say "stop"?
On the off-chance that you're not like every other xenophobic little-HTTPer
here, and you won't let any personal prejudices stop you from thinking
outside the Ajax-box for a moment, let me offer you a Java Applet
alternative. (If/when Flash or Silverlight get around to supporting UDP you
can probably do it with them as well.)
If you'd like to see an example of a threaded Java Applet that receives UDP
messages from an abitrary server(s), then please: -
1) Click on the following link and read the instructions:
http://manson.vistech.net/~tier3/tier3pager.html
2) Telnet to manson.vistech.net. (If you don't already have an account on
the Deathrow cluster then please use Username: DEMO Password: USER) and
then:
$set term/width=132
$run sys$users:[users.tier3.web]demo_udp_msg
3) Enter the IP address of your client node. Your "stock-monitor" from step
1 should now spring into life with random stock-prices generated at 2sec
intervals. (NATed clients will find this bit problematic :-)
4) Enter any adhoc messages that you wish to appear in the seperate Java
Frame on the client.
OPCOM messages to web-subscribers? CHAT conferences? Stock-Watching? Alarm
Monitoring? - It's all good!
The rationale here is not to use up a TCP/IP connection and a server
process/thread for ad-hoc, asynchronous, broadcasts, and most definitely do
use something other than a connectionless, context-devoid,
session-hijackable, pile of http-pooh as your middleware backbone.
Cheers Richard Maher
PS. The code for Tier3Pager.java aqnd DEMO_UDP_MSG.COB are below, but all
can be found at SYS$USERS:[USERS.TIER3.WEB]
PPS. If this is for the Intranet then you might wish to look at Broadcast or
even Multicast functionality as well, and eliminate the "subscribe" step
altogether.
Tier3Pager.java
===========
/**
* Copyight Tier3 Software. All rights reserved.
*
* Author: Richard Maher
*
**/
import java.applet.Applet;
import java.awt.*;
import java.net.*;
import java.io.IOException;
import netscape.javascript.JSObject;
import netscape.javascript.JSException;
public class Tier3Pager extends Applet
{
private String hostName;
private JSObject browser;
private static MessageThread socketThread;
private static Tier3Talk chat;
public class MessageThread extends Thread
{
private DatagramSocket socket;
private DatagramPacket packet;
private String threadData;
public MessageThread(String name, String txt) throws Exception
{
super(name);
byte[] buffer;
threadData = txt;
String port = getParameter("PORT");
String maxBuf = getParameter("MAXBUF");
try
{
if (port == null)
socket = new DatagramSocket();
else
socket = new DatagramSocket(Integer.parseInt(port));
if (maxBuf == null)
buffer = new byte[512];
else
buffer = new byte[Integer.parseInt(maxBuf)];
packet = new DatagramPacket(buffer, buffer.length);
}
catch (Exception e)
{
e.printStackTrace();
System.out.println("Unable to create UDP Socket");
throw new Exception("Message thread could not be created");
}
setDaemon(true);
start();
}
public void shutdown()
{
socket.close();
}
public int getLocalPort()
{
return socket.getLocalPort();
}
public void run()
{
System.out.println("Started Message thread. ThreadData = "
+threadData);
String args[] = {"Started Message Thread " + threadData};
browser.call("alert", args);
boolean stopThread = false;
readLoop:
while (!stopThread)
{
try
{
socket.receive(packet);
String received = new String(packet.getData(),
0,packet.getLength());
processMessage(received);
}
catch (SocketException e)
{
System.out.println("Shutting up shop");
stopThread = true;
continue readLoop;
}
catch (IOException e)
{
e.printStackTrace();
System.out.println("Unable to retrieve UDP message");
}
}
System.out.println("Thread run() unit terminating");
}
public void processMessage(String msgText)
{
int msgType = Integer.parseInt(msgText.substring(0,2));
switch (msgType){
case 1:
chat.append(msgText.substring(2));
break;
case 2:
String args[] = {msgText.substring(2)};
try {browser.call("priceUpdate", args);}
catch (JSException e)
{
System.out.println("Error when calling
JSpriceUpdate()");
}
break;
default:
System.out.println("Unknown rec type"+msgText);
}
}
}
public void init()
{
System.out.println("Initializing. . .");
hostName = getCodeBase().getHost();
chat = new Tier3Talk("Tier3 Messages");
requestFocus();
browser = JSObject.getWindow(this);
if (socketThread == null)
{
try
{
socketThread = new MessageThread("MsgDaemon", "SomeData");
}
catch (Exception e)
{
e.printStackTrace();
System.out.println("Could not init Tier3Pager");
}
}
}
public void alert(String alertText)
{
String args[] = {alertText};
browser.call("alert", args);
}
public void destroy()
{
if (chat != null)
chat.dispose();
boolean stillDying;
if (socketThread != null){
socketThread.shutdown();
do
{
stillDying = false;
System.out.println("Joining MessageThread");
try {socketThread.join();}
catch (InterruptedException e){
System.out.println("Interrupted Join");
stillDying = true;
}
} while (stillDying);
socketThread = null;
}
System.out.println("Tier3Pager Applet Rundown complete");
super.destroy();
}
}
"Anil" <anil...@gmail.com> wrote in message
news:ff0241de-724d-4ef4...@a70g2000hsh.googlegroups.com...
There's just a single thread. No new threads will be created, no,
never.
IOW, callback() won't be called until after work() completes.
Consider this work() function: ("stop" being a global) :
function work () {
while (!stop) {
//keep working
}
}
and this callback():
function onReadyStateChangeCallBack () {
if ((xhr.readyState > 3) && (xhr.status === 200)) {
stop= (xhr.responseText === "stop");
}
}
The above code won't work. The reason is that in order to give a
chance to the JS interpreter to call onReadyStateChangeCallBack(),
work() has to complete first, but it won't unless the callBack gets
called. Therefore it's a deadlock.
Consider this work() function instead:
function work () {
doJustALittleBitOfWorkAtATime();
if (!stop) {
setTimeout(arguments.callee, 0)
}
}
Now, work() isn't locked in an endless loop that prevents
onReadyStateChangeCallBack() to be called: every time work() is re-
scheduled to run again a.s.a.p. by the setTimeout(work, 0), the
interpreter has the chance to service any pending callbacks (and it
will do so before returning to "work").
HTH,
--
Jorge.
Thanks Jorge, I shall try your solution doJustALittleBitOfWorkAtATime
();
It seemed to me that an embedded media player in the browser creates a
new thread so that things won't block.
-
Anil