How to replace ajax with webrtc data channel - javascript

** JAVASCRIPT question **
I'm using regularly ajax via XMLHttpRequest. But in 1 case, I need 1 ajax call per seconds....
but long term wise and with growing number of simultaneous users, it could bloat easily...
I'm reading stuff about webRTC data channel and it seems interesting and promissing.
Here my working AJAX function as an example of how easy and there is a few lines of codes to communicate from the browser to the server and vice-versa
function xhrAJAX ( divID , param2 ) {
// random value for each call to avoid cache
var pcache = (Math.floor(Math.random() * 100000000) + 1);
// parameters
var params = "divID="+encodeURIComponent(divID)+"&param2="+encodeURIComponent(param2);
// setup XMLHttpRequest with pcache
var xhr = new XMLHttpRequest();
xhr.open("POST", "/file.php?pcache="+pcache, true);
// setup headers
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
// prepare onready scripts
xhr.onreadystatechange = function(e) { if (xhr.readyState == 4) { $("#"+divID).html(e.currentTarget.responseText) ; } }
// send the ajax call
xhr.send(params);
}
How can I "transpose" or "convert" this ajax workflow into a webRTC data channel ? in order to avoid to setup a setInterval 1000...
Note: I mean how to replace the javascript portion of the code. PHP here is only to illustrate, I don't want to do a webRTC via PHP...
Is there a simple few lines of code way to push/receive data like this ajax function ?
the answer I'm looking for is more like a simple function to push and receive
(once the connection with STUN, ICE, TURN is established and working...)
If I need to include a javascript library like jquery or the equivalent for webRTC, I'm welcoming good and simple solution.
*** The main goal is this kind of scenario :
I have a webapp : users in desktop and users within webview in Android and IOS
right now I have this workflow => ajax every 3 seconds to "tell" the main database that the user is still active and using the browser (or the app)
But I'd like to replace with this kind : when the user uses the browser => do a webrtc data chata in background between the browser and the server
While reading on the web I think that webRTC is a better solution than websocket.
** I did a bit of search and found peerjs....
https://github.com/jmcker/Peer-to-Peer-Cue-System/blob/main/send.html
I'll do some testing, but in the meantime, if someone can trow ideas, it could be fun.
Cheers

Related

How to recreate Chrome Waterfall column (Network tab) that documents time required for different stages of network request for jQuery AJAX call?

This question is similar but not helpful.
To provide more feedback to users, we want to mimic the Waterfall column in the Network tab of Chrome, which deconstructs network requests into different stages and times them.
An example is included below.
In the particular, we want to indicate three stages:
Time uploading a file
Time processing a file on the server
Time download results
From the jQuery AJAX docs, it seems like beforeSend could be used to time file uploads. How about download time and time on server (TTFB in screenshot)?
Here's how we implement AJAX calls:
async function doRequest() {
// Set server URL.
let serverUrl = 'https://test.com/test';
// Set form data
let imageFile = imageFile
// Create request form.
let formData = new FormData();
formData.append('imageFile', imageFile);
// Set request settings.
let settings = {
url: serverUrl,
method: 'POST',
timeout: 0,
contentType: false,
processData: false,
data: formData,
xhr: function() {
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == 2) {
if (xhr.status == 200) {
xhr.responseType = 'blob';
} else {
xhr.responseType = 'text';
}
}
};
return xhr;
},
};
// Make request.
try {
let result = await $.ajax(settings);
// Handle success
} catch (error) {
// Handle failure
}
}
Resource Loading and Timing
As usual, someone had the same idea and has provided a pre-coded solution. I discovered these resources in an attempt to help you with this very complicated task. You can use the code as written or place it into a bookmarklet.
I found a detailed article that describes how to use both the Navigation Timing API & the Resource Timing API The article I came across is titled (and found at):
Assessing Loading Performance in Real Life with Navigation and Resource Timing
The two prebuilt solutions provided by that article take completely different approaches to visualizing the data you seek.
To use them without any effort, create a book mark for each of the following URLs:
More Detailed Analysis <-- copy this link to your bookmarks collection
Performance Waterfall <-- copy this link to your bookmarks collection
As mentioned, these are bookmarklets. They contain JavaScript code that can be executed directly on the page you have loaded. To use them,
Load the page in Chrome that you want performance data
Open you bookmarks and click on one of the two bookmarklets provided here
The result will be the waterfall or other detailed data you are seeking.
Note: The script can be blocked by content-security-policy and may not
work on all sites.
Source Code
The waterfall chart like you originally asked about can be found at the following link. Note I am hosting this file for your answer. I can't guarantee it will be available forever. Please download and host the file. (Open License)
Waterfall by Andy Davies
The more detailed version is found here: (MIT License)
Performance-Bookmarklet by Michael Mrowetz.
File Upload
You'll see the Resource Timing API provides this data. If you prefer to use the XHR API the a simple way to measure file upload time is by using xhr.upload object which takes an event listener for progress. As pointed out, this isn't necessary given the previous tools.
xhr.upload.addEventListener("progress", function(evt){
// Initialize and finalize a timer here
if (evt.lengthComputable) {
console.log(evt.loaded + "/" + evt.total);
}
}, false);
Server Processing Time
In order to achieve the goal of measuring performance of the server and reporting it back to the client, the server must be involved in order to share its internal processing timing that you seek in your question. There is no way to determine that from the browser alone.
I recommend the use of the Server-Timing feature with details about its use in the PerformanceServerTiming API
It is fairly simple to use this API. As the example shows (using a NodeJS server), all your server has to do is respond with a specific HTTP header that contains the performance data you would like to display in the browser:
const headers = {
'Server-Timing': `
cache;desc="Cache Read";dur=23.2,
db;dur=53,
app;dur=47.2
`.replace(/\n/g, '')
};
Using the information on the client is as simple as this (from the MDN link page):
let entries = performance.getEntriesByType('resource');
console.log(entries[0].serverTiming);
// 0: PerformanceServerTiming {name: "cache", duration: 23.2, description: "Cache Read"}
// 1: PerformanceServerTiming {name: "db", duration: 53, description: ""}
// 2: PerformanceServerTiming {name: "app", duration: 47.2, description: ""}
For monitoring the upload state, I think you need XMLHttpRequestUpload and request.upload.addEventListener("progress", updateProgress) or request.onprogress and onloadend to check the loadend event. See https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/upload.
I don't see there is a partucular HTTP state to determine the start of a response from a server. Check https://developer.mozilla.org/en-US/docs/Web/HTTP/Status. So from the HTTP API level (XMLHttpRequest) I dont think you can find a clue of that. But the browser should be able to know from TCP level. If checking devtools is not your preference, you may need to specify the timestamp in the response. Once the client gets the response, the client knows the start time of the response.
The client can easily get the time that it receives the response from the server.
So
Dur_uploading = Time_loadend - Time_requeststarts
Dur_serverprocessing = Time_responsespecified - Time_loadend
Dur_download = Time_responsereceived - Time_resonsespecified

How to make JS wait until protocol execution finished

I have a custom URL protocol handler cgit:[...]
It launches up a background process which configures some stuff on the local machine. The protocol works fine, i'm launching it from JavaScript (currently using document.location = 'cgit:[...]'), but i actually want JavaScript to wait until the associated program exits.
So basically the steps i want JavaScript to do:
JavaScript does something
JavaScript launches cgit:[...]
Javascript waits until cgit:[...] exits
JavaScript does something else
Code:
function launchCgit(params)
{
showProgressBar();
document.location="cgit:"+params;
document.addEventListener( /* CGit-Program exited event */, hideProgressBar );
}
or:
function launchCgit(params)
{
showProgressBar();
// setLocationAndWait("cgit:"+params);
hideProgressBar();
}
Any ideas if this is possible?
Since this isn't really an expected use of window.location I would doubt that there's an easy way. My recommendation would be to use an AJAX request and have the c++ program send a response when it's done. That way, whatever code needs to run after the c++ program can be run when the request completes.
As i didn't find a suitable way to solve my problem using ajax requests or anything similar, i finally solved my problem using a kind-of-ugly workarround including XmlHttpRequest
For launching the protocol i'm still using document.location=cgit:[...]
I'm using a server side system including "lock-files" - that's like generic dummy files, with generated names for each request.
Once the user requests to open the custom protocol, such a file is being generated on the server specifically for that one protocol-opening-request.
I created a folder called "$locks" on the server where these files are being placed in. Once the protocol-associated program exits, the appropriate file is being deleted.
The website continuously checks if the file for a request still exists using XmlHttpRequest and fires a callback if it doesn't (example timout between tests: 1 sec).
The structure of the new files is the following:
lockThisRequest.php: It creates a file in the $locks directory based on the req url-parameter.
unlockThisRequest.php: It deletes a file in the $locks directory; again based on the req url-parameter.
The JavaScript part of it goes:
function launchCgit(params,callback)
{
var lock = /* Generate valid filename from params variable */;
// "Lock" that Request (means: telling the server that a request with this ID is now in use)
var locker = new XmlHttpRequest();
locker.open('GET', 'lockThisRequest.php?req='+lock, true)
locker.send(null);
function retry()
{
// Test if the lock-file still exists on the server
var req = new XmlHttpRequest();
req.open('GET', '$locks/'+lock, true);
req.onReadyStateChanged=function()
{
if (req.readyState == 4)
{
if (req.status == 200)
{
// lock-file exists -> cgit has not exited yet
window.setTimeout(retry,1000);
}
else if (req.status == 404)
{
// lock-file not found -> request has been proceeded
callback();
}
}
}
req.send(null);
}
document.location = 'cgit:'+params; // execute custom protocol
retry(); // initialize lockfileCheck-loop
}
Ussage is:
launchCgit("doThisAndThat",function()
{
alert("ThisAndThat finished.");
});
the lockThisRequest.php-file:
<?php
file_put_contents("$locks/".$_GET["req"],""); // Create lock file
?>
and unlockThisRequest.php:
<?php
unlink("../\$locks/".$_GET["req"]); // Delete lock file
?>
The local program / script executed by the protocol can simply call something like:
#!/bin/bash
curl "http://servername/unlockThisRequest.php?req=$1"
after it finished.
As i just said this works, but it's anything else than nice (congratulations if you kept track of those instructions)
I'd rather prefered a more simple way and (important) this also may cause security issues with the lockThisRequest.php and unlockThisRequest.php files!
I'm fine with this solution, because i'm only using it on a password protected private page. But if you plan to use it on a public or non protected page, you may want to add some security to the php files.
Anyways, the solution works for me now, but if anyone finds a better way to do it - for example by using ajax requests - he/she would be very welcome to add that way to the respective stackoverflow-documentation or the like and post a link to it on this thread. I'd still be interested in alternative solutions :)

Server doesn't respond to an xmlHTTP request using the get method

I'm doing a project with arduino in which I send different requests to the server (the arduino board) with the method XMLHttprequest and Get from a webpage. Except one of the request the others are used only for sending orders to the server, so I don't expect for an XML response. The other one is a request sent in intervals of 5 seconds for getting different values from the server.
The problem arrives with this last one. Actually the webpage sends the request (because I see it on the browser console and the arduino serial monitor) every 5 seconds, but it doesn't get anything, just the headers of the answer confirming the response but nothing about the XML file. Surprisingly, when I write a normal request using the get method in the browser I get instantly the XML file with the values, and It happens all the time I do that.
I'm going to write the javascript code I'm using on the webpage
setInterval(function tiempo()
{
var request = new XMLHttpRequest();
request.onreadystatechange = function()
{
if (this.readyState == 4) {
if (this.status == 200) {
if (this.responseXML != null) {
// extract XML data from XML file (containing switch states and analog value)
document.getElementById("input1").innerHTML = this.responseXML.getElementsByTagName('dato')[0].childNodes[0].nodeValue;
document.getElementById("input2").innerHTML = this.responseXML.getElementsByTagName('dato')[1].childNodes[0].nodeValue;
document.getElementById("input3").innerHTML = this.responseXML.getElementsByTagName('dato')[2].childNodes[0].nodeValue;
document.getElementById("input4").innerHTML = this.responseXML.getElementsByTagName('dato')[3].childNodes[0].nodeValue;
document.getElementById("input5").innerHTML = this.responseXML.getElementsByTagName('dato')[4].childNodes[0].nodeValue;
document.getElementById("input6").innerHTML = this.responseXML.getElementsByTagName('dato')[5].childNodes[0].nodeValue;
document.getElementById("input7").innerHTML = this.responseXML.getElementsByTagName('dato')[6].childNodes[0].nodeValue;
}
}
}
}
request.open("GET", "URL" + Math.random(), true);
request.send(null);
}
, 5000);
On the other hand, if I only write in the browser URL, I get the XML without any problem.
One las thing I have to say is that right now I'm using a webpage stored in my computer but before I was using a webpage stored in the arduino (on an SD card) and loaded also through the internet from arduino. The same code in that case worked perfectly. The reason because I changed It is because arduino ethernet is not too fast and It took so much time. With the webpage stored in my computer It goes faster because It only needs to send the orders.
Thanks!!
Finally, I figured out the problem. It is the browser. For any reason only Internet Explorer works correctly with the webpage. Neither firefox nor other web browsers got the xml file. I don't know the reason but I would like to find it.
If someone knows something about I would be glad of trying to resolve the problem.
Thanks!!

How to interactively get data from php script using javascript

I have this php script:
<?php
$arr = array(array("a","b"),array("c","d"));
qq($arr);
function qq($arr){
foreach($arr as $ar => $r){
//getting some work done
//sending the array $r (or values)to javascript
}
}
?>
Is it possible to get the value of 0 array using javascript before array 1.
what i get so far is this js from stackoverflow:
<script type="text/javascript">
function q(){
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", "http://127.0.0.0.1/q.php");
xmlhttp.send(null);
xmlhttp.onreadystatechange = callbackFunction;
function callbackFunction(){
if (xmlhttp.readyState == 4){
xml = xmlhttp.responseText;
document.getElementById("q").value = xml;
}}}
</script>
but it's not doing what i want(i think i'm missing something).
my html:
<input type="submit" onclick="q();" />
<div id="q"></div>
<div id="q1"></div>
Is it possible to put array 0 value in div(id=q) and when array 1 is ready put it's value in div(id=q1)
The "normal" HTTP Requests via XMLHttpRequest() do not allow such behaviour in a single request.
You have the following options instead:
Server Send Events
upside
They are incredibly easy to build. Nothing really special is needed on the server. Just google for server sent events and you'll find some examples on how they work.
They go through proxys and firewalls just as well as any other http request, because it is a normal http request.
downside
Does not run on Internet Explorer (?)
May fail to update in realtime if a proxy somewhere buffers too much. However in this case it still works, it just misses the realtime communication
Websockets
upside
Works in all recent browsers. Enables you to do full duplex communication and gets everything right that you need.
downside
May or may not work through proxies depending on their configuration.
Special extensions are needed on the server
(Long-) polling
upside
Best compatibility (works even in older browsers, no issues with proxies or firewalls)
downside
Creates lots of overhead because it does create for each message a new http connection
You need to store intermediate results somewhere because the poll requests come in different threads to your application than your code generation mechanism.
can you try with
if (xmlhttp.readyState == 4){
xml = xmlhttp.responseText;
document.getElementById('q').innerHTML=xml;
}}}

How to show loading status in percentage for ajax response?

I want to show the user percentage of the ajax response loaded with a progressbar.
Is there a way to achieve it?
Right now I am showing just an image.
Here is my code sample :
$('#loadingDiv').show();
$.ajax({
type : 'Get',
url : myUrl,
success : function(response) {
$('#loadingDiv').hide();
populateData(response);
},
error: function(x, e) {
$('#loadingDiv').hide();
if (x.status == 500 || x.status == 404) {
alert("no data found");
}
}
});
HTML code:
<div id="loadingDiv">
<img src="loading-img.png"/>
</div>
There are two ways to show real percentage. Briefly...
One - old school native JavaScript or jQuery ajax, for which you need server support as well, a different URL which can give you updates. And you keep hitting that URL on an interval.
Two - modern native native JavaScript in HTML5 browsers, supporting XMLHTTPRequest2, also known as AJAX 2, defined by new Web and HTML5 Standards.
If two, welcome to the new web!!
Multiple features have been added to Browsers that enhance connectivity - part of HTML5 features.
XMLHTTPRequest2 enables events in AJAX that help monitoring progress, as well as a lot of other things, from JavaScript itself. You can show the real percentage by monitoring the actual progress:
var oReq = new XMLHttpRequest();
oReq.addEventListener("progress", updateProgress, false);
oReq.addEventListener("load", transferComplete, false);
oReq.addEventListener("error", transferFailed, false);
oReq.addEventListener("abort", transferCanceled, false);
oReq.open();
Then you can define the handlers attached above (progress in your case):
function updateProgress (oEvent) {
if (oEvent.lengthComputable) {
var percentComplete = oEvent.loaded / oEvent.total;
// ...
} else {
// Unable to compute progress information since the total size is unknown
}
}
jQuery can be used in the second case as well. After all, jQuery is for helping you with less code, more doing!
Hoping that you are focusing on HTML5 and the new web solution, I would point you to Mozilla DOC - Monitoring Progress in AJAX from where I have taken this solution.
Every Browser now has a documentation for the web (like the one above from Mozilla) and additionally, all of them are contributing to a common venture called Web Platform, together with other influential Web and Internet giants - for a common updated Web Documentation. It is a work in progress, so not complete.
Also, there is no native functionality in the old AJAX, to monitor progress.
In the old-school way, you would have to create an interval function that would keep on hitting a separate URL to get the progress update. Your server also has to update the progress and send that as a response from that URL available from a different port.

Categories

Resources