receive multiple responses in javascript with one request - javascript

How can I receive multiple responses from a server using javascript.
I have a requirement where a request is posted one time with the data and number of iterations and at server side the request is processed for the number of iterations. On completion of each iteration the server sends back the response. So for one request and 10 iterations my java script need to receive the 10 responses and show it on the web page. Is there any way that I can handle this using javascript. I cannot use any other technology.
Right now I am using the following way
function showResponse(){
xmlHttp = GetXmlHttpObject();
var dataString = document.getElementById("request-parameters").value;
var iterations = document.getElementById("iterations").value;
if(xmlHttp==null){
alert("your browser does not support AJAX!");
}
var url = "http://localhost:8080/servlet/requestServlet";
xmlHttp.onreadystatechange=stateChanged;
xmlHttp.open("POST",url,true);
xmlHttp.send(dataString);
}
function GetXmlHttpObject(){
var xmlHttp=null;
try{
//Firefox, Opera, Safari
xmlHttp=new XMLHttpRequest();
}catch(e){
//IE
try{
xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
}catch(e){
xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
}
}
return xmlHttp;
}
function stateChanged(){
if(xmlHttp.readyState==4){
if(xmlHttp.status == 200){
var resp = xmlHttp.responseText;
var responseDiv = document.getElementById("response");
responseDiv.innerHTML=responseDiv.innerHTML+resp1[1];
}
}
}
I cannot modify this approach. Is it possible to get it done with XmlHttp object.

With just 'basic javascript' you cannot do this.
It just works like this: Client sends request, servers returns 'something'. The server cannot simply keep sending data back to this client for multiple reasons. A: There is not a 'link' aka connection between both party's except for the first 'call' of a request, but the client just waits for the response.
B: The script does not expect an other answer back.
What you need is a websocket for example. This way the client can listen to the server and actually process data send from the server to the client.
So in short:
Javascript works always like this:
Client -> Server | and the server respond back
For a socket you can have:
Client -> Server
Server -> Client
You can use some sort of 'javascript' even tho its a different technology.. like NodeJS.
The other way is to make a loop. Rather than posting a dataset with an amount of iterations, just iterate it in JS and for each iteration send it to the server to actually 'perform' on your data.

1) HTTP Try request once to one controller, and then get answer from other controller, you can do this with jQuery or with native XmlHttpRequest (it is not one request).
$.get("server/controllerJob",{data:"data"});
var askInterval = window.setInterval(function(){
$.get("server/askAnswerFromJob",{data:"data"}).done(function( data ) {
if(data.complete){
/** do staff**/
window.clearInterval(askInterval);
}else{
/** do staff**/
}
});
},200);
2) webSocket Or try to find something about WebSocket webSocket documentation, it is techonolgy with one connection with multiple request and response (full-duplex connection stream).
Also you need other server controller realization and see websocket
supported browsers
Notice the ws:. This is the new URL schema for WebSocket connections.
There is also wss: for secure WebSocket connection the same way https:
is used for secure HTTP connections
I'm only just noticing that the "examples" web app that comes with
Tomcat 7 contains 4 complete examples of how to use WebSocket (for java developers)
var connection = new WebSocket('ws://server/yourService',['soap','xmpp']);
connection.onopen = function () {
connection.send('ask'); // Send the message to server
};
//Each time on new messages from server, this callbacks will be executed (depends on result)
// Log errors from server
connection.onerror = function (error) {
console.log('WebSocket Error ' + error);
};
// Get messages from the server
connection.onmessage = function (e) {
console.log('Answer: ' + e.data);
};

Related

Make changes instantly PHP or Javascript [duplicate]

This question already has answers here:
Short-polling vs Long-polling for real time web applications?
(3 answers)
Closed 12 months ago.
I have a chat system but I want both the notifications and the messages to be updated immediately, I am using this code (setInterval) but it makes requests every 500 seconds so I think it is not very efficient, is there another way to do it?
setInterval(() => {
let xhr = new XMLHttpRequest();
xhr.open("POST", "INCLUDES/funciones/get-chat.php", true);
xhr.onload = () => {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
let data = xhr.response;
chatBox.innerHTML = data;
if (!chatBox.classList.contains("active")) {
}
}
}
}
let formData = new FormData(form);
xhr.send(formData);
}, 500);
You should check WebSockets. You can lower the time between requests lowering the second parameter of setInterval but that would be bad. It would be a huge stress for your server that see a spike in the number of requests.
WebSocket, as the name said, open a socket, a permanent comunication channel between the server and client. This allows the server to send messages to the client.
The advantage is that if no message is ready for the client no traffic is sent and no new requests are made from the client to the server.
This is not the right place for a full chat code example because it's quite long. You can see Socket.io not the fastest but maybe the easiest library to work with WebScokets. Here you can find an example of a working chat (server and client) using Socket.IO

python socket - cant get sent data from javascript

I'm trying to make a javascript program send data to a python socket but it doesn't receive the right data.
I want python to print 'aaaa'.
Here is my javascript code:
function createCORSRequest(method, url) {
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr) {
xhr.open(method, url, true);
} else if (typeof XDomainRequest != "undefined") {
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
xhr = null;
}
return xhr;
}
var xhr = createCORSRequest('GET', "http://192.168.1.10:12345");
xhr.send("aaaa");
Here is my python code:
import socket
s = socket.socket()
host = socket.gethostname()
port = 12345
BUFFER_SIZE = 1024
s.bind(('', port))
s.listen(5)
while True:
c, addr = s.accept()
print ('Got connection from', addr)
c.send(bytes('Thank you for connecting','UTF-8'))
data = c.recv(BUFFER_SIZE)
print(data)
c.close()
You are doing an XMLHttpRequest, which is a HTTP request. But your python server does not handle the HTTP protocol at all. Handling HTTP would mean to read the HTTP request header, read the body based on the information in the header and return a proper HTTP response.
You are doing a HTTP GET requests. A GET requests takes no payload so any body data you add (i.e. the "aaaa" in your xhr.send("aaaa")) will be ignored (means: not send). To send a HTTP body use request types like POST.
Steffen's answer is correct (at least in general - can't comment on the JS specifics). In addition, it's always a good idea to independently verify the moving parts of your application, so that you can narrow down where the problem is.
Here's how you can verify that your python server works from the command line:
Start the server
In another terminal window, connect to it using telnet
telnet localhost 12345
(It will first try connecting using IPv6, fail, and fall back to IPv4)
You will see your welcome message returned to the client. Enter some text and press Enter.
The server will print your message and close the connection to the client.
Using your code, here's how it will look for the client. I'm sending the text meow to the server:
margold#home-macbook ~ $ telnet 127.0.0.1 12345
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Thank you for connectingmeow
Connection closed by foreign host.
And for the server:
margold#home-macbook ~ $ ./server.py
('Got connection from', ('127.0.0.1', 61148))
meow

Error handling over websockets a design dessision

Im currently building a webapp that has two clear use cases.
Traditional client request data from server.
Client request a stream from the server after wich the server starts pushing data to the client.
Currently im implementing both 1 and 2 using json message passing over a websocket. However this has proven hard since I need to handcode lots of error handling since the client is not waiting for the response. It just sends the message hoping it will get a reply sometime.
Im using Js and react on the frontend and Clojure on the backend.
I have two questions regarding this.
Given the current design, what alternatives are there for error handling over a websocket?
Would it be smarter to split the two UC using rest for UC1 and websockets for UC2 then i could use something like fetch on the frontend for rest calls.
Update.
The current problem is not knowing how to build an async send function over websockets can match send messages and response messages.
Here's a scheme for doing request/response over socket.io. You could do this over plain webSocket, but you'd have to build a little more of the infrastructure yourself. This same library can be used in client and server:
function initRequestResponseSocket(socket, requestHandler) {
var cntr = 0;
var openResponses = {};
// send a request
socket.sendRequestResponse = function(data, fn) {
// put this data in a wrapper object that contains the request id
// save the callback function for this id
var id = cntr++;
openResponses[id] = fn;
socket.emit('requestMsg', {id: id, data: data});
}
// process a response message that comes back from a request
socket.on('responseMsg', function(wrapper) {
var id = wrapper.id, fn;
if (typeof id === "number" && typeof openResponses[id] === "function") {
fn = openResponses[id];
delete openResponses[id];
fn(wrapper.data);
}
});
// process a requestMsg
socket.on('requestMsg', function(wrapper) {
if (requestHandler && wrapper.id) {
requestHandler(wrapper.data, function(responseToSend) {
socket.emit('responseMsg', {id: wrapper.id, data; responseToSend});
});
}
});
}
This works by wrapping every message sent in a wrapper object that contains a unique id value. Then, when the other end sends it's response, it includes that same id value. That id value can then be matched up with a particular callback response handler for that specific message. It works both ways from client to server or server to client.
You use this by calling initRequestResponseSocket(socket, requestHandler) once on a socket.io socket connection on each end. If you wish to receive requests, then you pass a requestHandler function which gets called each time there is a request. If you are only sending requests and receiving responses, then you don't have to pass in a requestHandler on that end of the connection.
To send a message and wait for a response, you do this:
socket.sendRequestResponse(data, function(err, response) {
if (!err) {
// response is here
}
});
If you're receiving requests and sending back responses, then you do this:
initRequestResponseSocket(socket, function(data, respondCallback) {
// process the data here
// send response
respondCallback(null, yourResponseData);
});
As for error handling, you can monitor for a loss of connection and you could build a timeout into this code so that if a response doesn't arrive in a certain amount of time, then you'd get an error back.
Here's an expanded version of the above code that implements a timeout for a response that does not come within some time period:
function initRequestResponseSocket(socket, requestHandler, timeout) {
var cntr = 0;
var openResponses = {};
// send a request
socket.sendRequestResponse = function(data, fn) {
// put this data in a wrapper object that contains the request id
// save the callback function for this id
var id = cntr++;
openResponses[id] = {fn: fn};
socket.emit('requestMsg', {id: id, data: data});
if (timeout) {
openResponses[id].timer = setTimeout(function() {
delete openResponses[id];
if (fn) {
fn("timeout");
}
}, timeout);
}
}
// process a response message that comes back from a request
socket.on('responseMsg', function(wrapper) {
var id = wrapper.id, requestInfo;
if (typeof id === "number" && typeof openResponse[id] === "object") {
requestInfo = openResponses[id];
delete openResponses[id];
if (requestInfo) {
if (requestInfo.timer) {
clearTimeout(requestInfo.timer);
}
if (requestInfo.fn) {
requestInfo.fn(null, wrapper.data);
}
}
}
});
// process a requestMsg
socket.on('requestMsg', function(wrapper) {
if (requestHandler && wrapper.id) {
requestHandler(wrapper.data, function(responseToSend) {
socket.emit('responseMsg', {id: wrapper.id, data; responseToSend});
});
}
});
}
There are a couple of interesting things in your question and your design, I prefer to ignore the implementation details and look at the high level architecture.
You state that you are looking to a client that requests data and a server that responds with some stream of data. Two things to note here:
HTTP 1.1 has options to send streaming responses (Chunked transfer encoding). If your use-case is only the sending of streaming responses, this might be a better fit for you. This does not hold when you e.g. want to push messages to the client that are not responding to some sort of request (sometimes referred to as Server side events).
Websockets, contrary to HTTP, do not natively implement some sort of request-response cycle. You can use the protocol as such by implementing your own mechanism, something that e.g. the subprotocol WAMP is doing.
As you have found out, implementing your own mechanism comes with it's pitfalls, that is where HTTP has the clear advantage. Given the requirements stated in your question I would opt for the HTTP streaming method instead of implementing your own request/response mechanism.

signalr - with different clients

I am trying to setup a signalR system.
I have the sample code working, using two browsers and the same hub. messages are sent and received.
Now, when I created a different page, and try to send messages to the hub, it appears to be kinda working, meaning it doesn't blow up, but nothing gets transmitted to the other clients.
I thought I was accessing the same message hub, from all the clients, but maybe I am missing something.
Is it possible to connect different web sites to the same message hub?
Begin Edit
As requested.... here is the code i am using on my second client...
var connection = $.hubConnection('http://xxxxxxxxx.azurewebsites.net/');
var contosoChatHubProxy = connection.createHubProxy('MessagePump');
// contosoChatHubProxy.on('Send', function (name, message) {console.log(name + ' ' + message);});
$.connection.hub.start()
.done(function () {
console.log('Now connected, connection ID=' + $.connection.hub.id); // returns an ID
// $.connection.hub.send('testing', 'this is a test from the client');
// contosoChatHubProxy.send("testing");
// contosoChatHubProxy.invoke('testing', 'this is a test for the client 1');
// contosoChatHubProxy.invoke('say', 'this is a test for the client 2');
// contosoChatHubProxy.invoke('Send', 'This is a test for client 3');
// $.connection.hub.send('testing', 'this is a test from the client 4');
contosoChatHubProxy.invoke('messagePump', 'user', 'this is a test message for 5');
})
.fail(function(){ console.log('Could not Connect!'); });
This is what i am seeing in firebug
From what i can make of the code, the proxy appears to be loading locally, and not even seeing the remote system hub...
My console application(s) that only connect to the remote system hub are able to send and receive messages.
btw - i have tried upper can lower case (MessagePump, messagePump)
but it has not changed the result.
var connection = $.hubConnection('http://xxxxxxxxx.azurewebsites.net/');
You are trying to connect a different website. This http://xxxxxxxxx.azurewebsites.net/ should let cross domain requests.Otherwise you can't connect. If you can manage http://xxxxxxxxx.azurewebsites.net/, you should configure signalr like:
public class Startup
{
public void Configuration(IAppBuilder app)
{
// Branch the pipeline here for requests that start with "/signalr"
app.Map("/signalr", map =>
{
// Setup the CORS middleware to run before SignalR.
// By default this will allow all origins. You can
// configure the set of origins and/or http verbs by
// providing a cors options with a different policy.
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
// You can enable JSONP by uncommenting line below.
// JSONP requests are insecure but some older browsers (and some
// versions of IE) require JSONP to work cross domain
// EnableJSONP = true
};
// Run the SignalR pipeline. We're not using MapSignalR
// since this branch already runs under the "/signalr"
// path.
map.RunSignalR(hubConfiguration);
});
}
}

Node.js WebSocket Broadcast

I'm using the ws library for WebSockets in Node.js and
I'm trying this example from the library examples:
var sys = require("sys"),
ws = require("./ws");
ws.createServer(function (websocket) {
websocket.addListener("connect", function (resource) {
// emitted after handshake
sys.debug("connect: " + resource);
// server closes connection after 10s, will also get "close" event
setTimeout(websocket.end, 10 * 1000);
}).addListener("data", function (data) {
// handle incoming data
sys.debug(data);
// send data to client
websocket.write("Thanks!");
}).addListener("close", function () {
// emitted when server or client closes connection
sys.debug("close");
});
}).listen(8080);
All OK. It works, but running 3 clients, for instance, and sending "Hello!" from one will make the server only reply "Thanks!" to the client which sent the message, not to all.
How can I broadcast "Thanks!" to all connected clients when someone sends "Hello!"?
Thanks!
If you want to send out to all clients, you have to keep track of them. Here is a sample:
var sys = require("sys"),
ws = require("./ws");
// # Keep track of all our clients
var clients = [];
ws.createServer(function (websocket) {
websocket.addListener("connect", function (resource) {
// emitted after handshake
sys.debug("connect: " + resource);
// # Add to our list of clients
clients.push(websocket);
// server closes connection after 10s, will also get "close" event
// setTimeout(websocket.end, 10 * 1000);
}).addListener("data", function (data) {
// handle incoming data
sys.debug(data);
// send data to client
// # Write out to all our clients
for(var i = 0; i < clients.length; i++) {
clients[i].write("Thanks!");
}
}).addListener("close", function () {
// emitted when server or client closes connection
sys.debug("close");
for(var i = 0; i < clients.length; i++) {
// # Remove from our connections list so we don't send
// # to a dead socket
if(clients[i] == websocket) {
clients.splice(i);
break;
}
}
});
}).listen(8080);
I was able to get it to broadcast to all clients, but it's not heavily tested for all cases. The general concept should get you started though.
EDIT: By the way I'm not sure what the 10 second close is for so I've commented it out. It's rather useless if you're trying to broadcast to all clients since they'll just keep getting disconnected.
I would recommend you to use socket.io. It has example web-chat functionality out of the box and also provides abstraction layer from the socket technology on client (WebSockets are supported by Safari, Chrome, Opera and Firefox, but disabled in Firefox and Opera now due to security vulnerabilities in ws-protocol).

Categories

Resources