The idea is to start multiple xmlhttp requests in an loop and let them store their result in a global variable.
for (var i = 0; i < something; i++) {
fetch_site(url, i);
}
Now the function fetch_site() looks like this:
// the result will be palced at the i-th field in the "content"-array
function fetch_site(url, i) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", url, true);
// Milliseconds a request can take before automatically being terminated
xmlhttp.timeout = 500;
xmlhttp.ontimeout = function () {
content[i] = "none";
console.log("ontimeout: content[" + i + "] is now set to " + content[i] );
};
// On error
xmlhttp.onerror = function () {
content[i] = "none";
console.log("onerror: content[" + i + "] is now set to " + content[i] );
};
// On success
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {
if (xmlhttp.status == 200) {
content[i] = xmlhttp.responseText;
// Deleting unneccessary spaces
content[i] = content[i].trim();
} else content[i] = "none";
}
};
//xmlhttp.setRequestHeader("Content-type","Lookup/simple");
xmlhttp.send();
}
I can confirm that each an every request gets send. However google-chrome marks them as pending and when diggin deeper it defines them as stalled.
By the way, this code is used in a chrome extension. Hence it might be a permission problem. Though I would not expect it to be one as I have granted my extension to fetch every site.
The corresponding manifest-file includes the following lines:
"permissions": [
"storage",
"http://*/",
"https://*/"
],
Related
I am currently trying to run 2 separate XMLHTTPRequests in dynamics CRM Javascript to retrieve data from 2 different entities and run code depending on what is retrieved..
I've done my best to try and edit some names for security reasons, but the premise is the same.
My main problem is that the first run of the XMLHTTPRequest (the RA Banner) works fine, but then the second run (the Status Banner) the Readystate that is returned is 2 and stopping.
function FormBanners(formContext) {
//Clear the existing banners
formContext.ui.clearFormNotification("Notif1");
formContext.ui.clearFormNotification("Notif2");
//Get the customer/rep
var customer = formContext.getAttribute("customerid").getValue();
var rep = formContext.getAttribute("representative").getValue();
var contact;
//use the rep if there is one else use the customer
if (rep != null) {
contact = rep;
}
else if (customer!= null) {
contact = customer;
}
//Get the account
var account = formContext.getAttribute("accountfield").getValue();
//As there is a requirement for 2 XMLHTTPRequests we have to queue them
var requestURLs = new Array();
//There will always be a customers or rep on the form
requestURLs.push(Xrm.Page.context.getClientUrl() + "/api/data/v9.1/contacts?$select=new_RA,new_SC,new_VC,new_PR&$filter=contactid eq " + contact[0].id + "", true);
//there may not be an account
if (account) {
requestURLs.push(Xrm.Page.context.getClientUrl() + "/api/data/v9.1/accounts?$select=_new_statusLookup_value&$filter=accountid eq " + account[0].id + "", true);
}
var current = 0;
function getURL(url) {
var req = new XMLHttpRequest();
req.open("GET", requestURLs[current]);
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("Prefer", "odata.include-annotations=\"*\"");
req.onreadystatechange = function () {
if (this.readyState === 4) {
req.onreadystatechange = null;
if (this.status === 200) {
var result = JSON.parse(req.response);
// Creation of the RA Banner
if (current == 0) {
var RA = result.value[0]["new_RA#OData.Community.Display.V1.FormattedValue"];
var SC = result.value[0]["new_SC#OData.Community.Display.V1.FormattedValue"];
var VC = result.value[0]["new_VC#OData.Community.Display.V1.FormattedValue"];
var PR = result.value[0]["new_PR#OData.Community.Display.V1.FormattedValue"];
var Notif = "";
//Only create a notification if any of the above contain "Yes"
if (RA == "Yes" || SC == "Yes" || VC == "Yes" || PR == "Yes") { Notif = "The Customer/Rep has:" }
if (RA == "Yes") { Notif = Notif + " RA,"; }
if (SC == "Yes") { Notif = Notif + " SC,"}
if (VC == "Yes") { Notif = Notif + " VC,"}
if (PR == "Yes") { Notif = Notif + " PR."}
if (Notif != "") {
formContext.ui.setFormNotification(Notif, "INFO", "Notif1");
}
}
//Creation of the Status Banner
else if (current == 1) {
status = results.value[i]["_new_statusLookup_value"];
if (status) {
if (status[0].name != "Open")
var Notif = "The status for the organisation on this case is " + status[0].name + ".";
formContext.ui.setFormNotification(Notif, "INFO", "Notif2");
}
}
++current;
if (current < requestURLs.length) {
getURL(requestURLs[current]);
}
} else {
Xrm.Utility.alertDialog(req.statusText);
}
}
}; req.send();
}
getURL(requestURLs[current]);
}
Can anyone help me out?
So in my example I had made many mistakes. Taking Arun's advice I separated the function out, which made debugging far easier.. it instead was not failing on the XMLHTTP Request because that worked fine, but firefox was crashing when debugging.
So my issues were that I was in the second part:
Used the value of i for results (i was no longer defined)
Getting the "_new_statusLookup_value" would only provide the guid of the lookup I would instead want "_new_statusLookup_value#OData.Community.Display.V1.FormattedValue"
Lets not ignore the fact that because I had copied and pasted many iterations of this code that I was also using "results" instead of "result".
Many little mistakes.. but it happens! Thanks for the help, just goes to show.. typos are our downfall!
I know this question has been asked before, but I tried to apply the answers with no results.
I'm trying to do multiple requests on the same domain with a for loop but it's working for the entire record of my array.
Here is the code I use:
function showDesc(str) {
var prod = document.getElementsByName("prod_item[]");
var xhr = [], i;
for (i = 0; i < prod.length; i++) {
var txtHint = 'txtHint10' + i;
(function(i) {
var xhr = new XMLHttpRequest();
var url = "getDesc.php?q=" + str;
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
document.getElementById(txtHint).innerHTML = xhr.responseText;
}
};
xhr.open("GET", url, false);
xhr.send();
})(i);
}
}
PHP
<select name="prod_item[]" id="prod_item.1" onchange="showDesc(this.options[this.selectedIndex].value)"></select>
<div id="txtHint100"></div>
and then I will use dynamic table for the prod_item field and div_id.
Is there any mistake in my code?
I have the following code, which works (sort of). When I run it, the page displays information about the two coins, but returns 'undefined' for the coin price. The call to alert() indicates that the getCoinPrice function is running AFTER the main code. How do you execute the code so that the function call happens serially? If that's not possible, would it be better to learn to use the Fetch API?
Here's the code, in its entirety:
<html>
<body>
<h2>Use the XMLHttpRequest to get the content of a file.</h2>
<p id="demo"></p>
<script>
function getCoinPrice(id) {
var xhr = new XMLHttpRequest();
var URL = "https://api.coinmarketcap.com/v2/ticker/" + id + "/";
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
var Obj = JSON.parse(xhr.responseText);
var price = Obj.data.quotes.USD.price;
alert(price);
return(price);
}
}
xhr.open("GET", URL, true);
xhr.send();
}
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var myObj = JSON.parse(this.responseText);
var coins = [ "BTC","ETH" ]
for(j=0; j < coins.length; j++) {
for(i=0; i < myObj.data.length; i++) {
if (myObj.data[i].symbol == coins[j]) {
document.getElementById("demo").innerHTML +=
myObj.data[i].id + "," + myObj.data[i].name + "," +
myObj.data[i].symbol + "," +
getCoinPrice( myObj.data[i].id ) + "<br>" ;
}
}
}
}
};
xmlhttp.open("GET", "https://api.coinmarketcap.com/v2/listings/", true);
xmlhttp.send();
</script>
</body>
</html>
I have 2 functions:
function parseFriends_new(range) {
var xml = window.XMLHttpRequest ? new XMLHttpRequest : new ActiveXObject("Microsoft.XMLHTTP");
var params = "gwt.requested=" + gwtHash + "&refId=search-d-" + Date.now() + "&d.sq=&d.o=" + range + "&d.d=d.in";
xml.open("POST", "/dk?cmd=FriendsSearch", true);
xml.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xml.setRequestHeader('TKN', TKN);
xml.onreadystatechange = function() {
if (4 == xml.readyState && 200 == xml.status) {
}
}
xml.send(params);
}
function postNoteAndTag(friendsList, repostId, trashText) {...}
I need to execute postNoteAndTag after parseFriends_new
for (var i = 0, range = 0; i < 20; i++, range += 10)
{
parseFriends_new(range);
}
//wait for loop and then execute next code
postNoteAndTag(friendsList, repostId, trashText);
How to do this?
Since parseFriends_new is asynchronous you might need to modify it so that it works with callbacks:
function parseFriends_new(range, done) {
var xml = window.XMLHttpRequest ? new XMLHttpRequest : new ActiveXObject("Microsoft.XMLHTTP");
var params = "gwt.requested=" + gwtHash + "&refId=search-d-" + Date.now() + "&d.sq=&d.o=" + range + "&d.d=d.in";
xml.open("POST", "/dk?cmd=FriendsSearch", true);
xml.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xml.setRequestHeader('TKN', TKN);
xml.onreadystatechange = function() {
if (4 == xml.readyState && 200 == xml.status) {
}
// The AJAX request finished => we can invoke the callback.
// you could also pass it some result if needed
done();
}
xml.send(params);
}
and then:
// We've got 20 AJAX requests to make at total
var count = 20;
for (var i = 0, range = 0; i < count; i++, range += 10) {
parseFriends_new(range, function() {
--count;
if (count <= 0) {
// All AJAX requests have finished executing
// you can now do whatever you intended to do:
postNoteAndTag(friendsList, repostId, trashText);
}
});
}
Bear in mind though that this is an absolutely bad practice to be hammering your web server with so many requests in a burst. It's bad for your server, it's bad for the client, it's bad for the TCP/IP.
A much better solution is to send a single AJAX request to the server with all the payload. It's far more efficient to send one large AJAX request than multiple small. Of course you might need to adapt your server side script to be able to process the request.
While testing out setInterval(), i had a slow load time for an ajax request. It was very simple and other pages with much more complex requests were terminating in less than a second while this very simple one is terminating after 10-12. Without using setInterval() it is still taking this long and it uses the same layout as the other pages.
Example of script:
document.getElementById("test").innerHTML = "Starting";
if(window.XMLHttpRequest)
{
xmlhttp = new XMLHttpRequest();
}
else
{
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function()
{
if(xmlhttp.readyState == 4 && xmlhttp.status == 200)
{
document.getElementById("test").innerHTML = xmlhttp.responseText;
}
}
xmlhttp.open("GET", "/TestLive.cshtml", true);
xmlhttp.send();
Slow server page (ASP.NET):
Response.Expires = -1;
var db = Database.Open("mydb");
string query = "select Name from Game where ID='97';";
Response.Write(db.QuerySingle(query).Name);
Example of fast:
Response.Expires = -1;
string query = "select * from Season where Season.Game = 'Football' and Season.End > '" + DateTime.Now.Add(new TimeSpan(-8,0,0)).ToString("yyyy-MM-dd") + "';";
var db = Database.Open("mydb");
var result = db.Query(query);
Response.Write("<select id=\"chosenSeason\" onchange=\"setDraftSeason()\">");
Response.Write("<option selected=\"selected\">Choose a Season</option>");
foreach (var season in result)
{
Response.Write("<option value=\"" + season.ID + "\">");
Response.Write(season.Name);
Response.Write(" (" + season.Start.ToString("dd-MM-yyyy") + " - " + season.End.ToString("dd-MM-yyyy") + ")");
Response.Write("</option\">");
}
Response.Write("</select>");
EDIT: It seems to be related to using the layout page to access the script. all of the fast pages use the same setup though.