Converting XMLHttpRequest responseText to a variable and running if logic in readystate - xmlhttprequest

I've been trying to solve a coding issue for some days now.
I can't figure out how this asynchronous coding works despite reading several posts.
Hopefully someone on here can point me in the correct direction. Below is what I'm trying to achieve, seems though that I can't pass a responseText into a var.
Comparing responseText like this works: if (this.responseText > 10) {do something;}
setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
var peak;
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("value").innerHTML = this.responseText;
if (this.responseText > peak){
document.getElementById("valuePeak").innerHTML = this.responseText;
peak = this.responseText;
}
}
};
xhttp.open("GET", "/value", true);
xhttp.send();
}, 55 ) ;

Related

Uncaught TypeError: datapoints.data.map is not a function at XMLHttpRequest.xmlhttp.onreadystatechange

Can anyone help me? I'm really bad at programming
Error :Uncaught TypeError: datapoints.data.map is not a function at XMLHttpRequest.xmlhttp.onreadystatechange
const xmlhttp = new XMLHttpRequest();
const url = '//url//';
xmlhttp.open('GET', url, true);
xmlhttp.send();
xmlhttp.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
const datapoints = JSON.parse(this.responseText);
//console.log(datapoints);
const labelsboy = datapoints.data.map(function(item){
return item.boy;
});
console.log(labelsboy);
}
}
file JSON API
{
"status": true,
"row": 2,
"data": {
"boy": 10,
"girl": 15
}
}
map is an array function but datapoints.data is an object. It seems like you are just trying to get one value from the object so you can just access it directly.
const labelsboy = datapoints.data.boy;
console.log(labelsboy);

In Ionic and Vue.js. How to fetch or “call” data from one file to another?

I’m new to both Ionic and Vue.js. I’m taking advantage of this summer break to start learning both.
I’m building a mobile app for this purpose and so far, so good. However, I have found and issue that I hope you could help me with. Namely, how to fetch or “call” data from one file to another (Is it called routing?).
In my app, I am trying to start/open a function named myFunction() from one of the pages (quiz.vue) when I call it using v-on:click="myFunction3".
This function is located in a JS file called quizz.js, and it is located in the assets folder. This is its path: (“./assets/js/quizz.js”).
I have tried many things to make it work and finally it is working as it should. However, I think my solution is not optimal as it keeps throwing “Uncaught TypeErrors” in the console of the Developer’s Tool…even though it works.
My solution was to push the function inside methods: this.$router.push(myFunction3())
Also, when running the app, it says that myFunction() , and other functions in the same quizz.js file, “is define but never used”.
If you could advise me with anything, I would be most grateful. I am still a beginner so please explain it to me in as simple a manner as possible.
methods:{
openMenu(){
menuController.open("app-menu")
},
myFunction3(){
this.$router.push(myFunction3())
},
Below, the quizz.js file:
var mlhttp = new XMLHttpRequest();
mlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var myObj = JSON.parse(this.responseText);
const quiz = myObj.results[0]['question'];
const correctAnswer = myObj.results[0]['correct_answer'];
const incorrect = myObj.results[0]['incorrect_answers'];
incorrect.push(correctAnswer);
shuffle(incorrect);
document.getElementById("ans").innerHTML = quiz;
var text = "";
var val = 0;
var i;
for (i = 0; i < incorrect.length; i++) {
if(incorrect[i] == correctAnswer){
text += "<ion-button fill='outline' id='right' onClick='increment();myFunc();'/><b>" + incorrect[i] + "</b></ion-button></br>";
val = val + 1;
}else{
text += "<ion-button fill='outline' class='wrong' onClick='myFunc2();'/><b>" + incorrect[i] + "</b></ion-button></br>";
}
}
document.getElementById("ans5").innerHTML = text;
}
};
var j=0;
function myFunction3() {
document.getElementById("ans6").innerHTML = "";
mlhttp.open("GET", "https://opentdb.com/api.php?amount=1", true);
mlhttp.send();
j++;
document.getElementById('ans11').innerHTML=j;
}
function shuffle(array) {
for (let i = array.length - 1; i > 0; i--) {
let j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
function myFunc(){
document.getElementById("ans6").innerHTML = "<h1 style='color:green'><i class='fa fa-check'></i> That is correct!</h1>";
document.getElementById("right").style.color = "white";
document.getElementById("right").style.backgroundColor = "green";
var audio = new Audio('./assets/sound/win.mp3');
audio.play();
}
function myFunc2(){
document.getElementById("ans6").innerHTML = "<h1 style='color:red'><i class='fa fa-thumbs-down' ></i>Wrong Answer! </h1>";
document.getElementById("right").style.color = "white";
document.getElementById("right").style.backgroundColor = "green";
var x = document.getElementsByClassName("wrong");
var i;
for (i = 0; i < x.length; i++) {
x[i].style.backgroundColor = "rgba(255, 0, 0, 0.8)";
x[i].style.color = "white";
}
//document.getElementById("wrong").style.color = "red";
var audio = new Audio('./assets/sound/wrong.mp3');
audio.play();
}
var i=0;
function increment() {
i++;
document.getElementById('ans10').innerHTML=i;
}

QZ TRAY PRINITING ORDER NOT IN SEQ

I'm trying to print qz tray from javascript.
I have barcode with number in ascending order 1,2,3,4, 5 and so on.
I looping the seq correctly . but when printed out, it was not in order.
setTimeout("directPrint2()",1000);
function sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}
function directPrint2(){
var data;
var xhttp;
var v_carton = "' || x_str_carton ||'";
var carton_arr = v_carton.split('','');
var v1 = "' ||
replace(x_zebra_printer_id, '\', '|') ||
'".replace(/\|/g,"\\");
if(v1 == ""){
alert("Please setup ZPL Printer");
}
else{
xhttp=new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
data = [ toNative(this.responseText) ];
printZPL(data, v1);
}
};
for (var j = 0; j < carton_arr.length; j++){
var url = "' || x_wms_url ||
'WWW_URL.direct_print_label?in_carton_no="+toValidStr(carton_arr[j]);
xhttp.open("GET", url, false);
xhttp.send();
sleep(5000);
}
}
};
',
'javascript'
What's missing from your example:
I do not see any looping logic in the example calling the printZPL function,
printZPL isn't a QZ Tray function and you're missing the code snippet which it calls. Usually this would be qz.print(config, data);.
Regardless of the missing information, the qz.print(...) API is ES6/Promise/A+ based meaning if you want to call qz.print multiple times in a row you need to use a Promise-compatible technique. (e.g. .then(...) syntax) between your print calls as explained in the Chaining Requests guide.
To avoid this, you can concatenate all ZPL data into one large data array. Be careful not to spool too much data at once.
If you know exactly how many jobs you'll be appending, you can hard-code the promise chain:
qz.websocket.connect()
.then(function() {
return qz.printers.find("zebra"); // Pass the printer name into the next Promise
})
.then(function(printer) {
var config = qz.configs.create(printer); // Create a default config for the found printer
var data = ['^XA^FO50,50^ADN,36,20^FDRAW ZPL EXAMPLE^FS^XZ']; // Raw ZPL
return qz.print(config, data);
})
.catch(function(e) { console.error(e); });
Finally, if you do NOT know in advanced how many calls to qz.print(...) you can use a Promise loop as explained in the Promise Loop guide.
function promiseLoop() {
var data = [
"^XA\n^FO50,50^ADN,36,20^FDPRINT 1 ^FS\n^XZ\n",
"^XA\n^FO50,50^ADN,36,20^FDPRINT 2 ^FS\n^XZ\n",
"^XA\n^FO50,50^ADN,36,20^FDPRINT 3 ^FS\n^XZ\n",
"^XA\n^FO50,50^ADN,36,20^FDPRINT 4 ^FS\n^XZ\n"
];
var configs = [
{ "printer": "ZDesigner LP2844-Z" },
{ "printer": "ZDesigner LP2844-Z" },
{ "printer": "ZDesigner LP2844-Z" },
{ "printer": "ZDesigner LP2844-Z" }
];
var chain = [];
for(var i = 0; i < data.length; i++) {
(function(i_) {
//setup this chain link
var link = function() {
return qz.printers.find(configs[i_].printer).then(function(found) {
return qz.print(qz.configs.create(found), [data[i_]]);
});
};
chain.push(link);
})(i);
//closure ensures this promise's concept of `i` doesn't change
}
//can be .connect or `Promise.resolve()`, etc
var firstLink = new RSVP.Promise(function(r, e) { r(); });
var lastLink = null;
chain.reduce(function(sequence, link) {
lastLink = sequence.then(link);
return lastLink;
}, firstLink);
//this will be the very last link in the chain
lastLink.catch(function(err) {
console.error(err);
});
}
Note: The Promise Loop is no longer needed in QZ Tray 2.1. Instead, since 2.1, an array of config objects and data arrays can be provided instead.

Saving data from XMLHttpRequest Response to my IndexedDB

I have created a json file containing my Sql Server datas. With the XmlHttpRequest's GET method, I am reading json file and iterating and saving those records to my IndexedDB.. Everything is working fine.. After the end of the iteration, I wrote a code to alert the user.. But the alert message is displayed very quickly, but when I see it in the console window, the saving operation is till processing.. I want to alert the user, only after the operation is completed..
My code is,
if (window.XMLHttpRequest) {
var sFileText;
var sPath = "IDBFiles/Reservation.json";
//console.log(sPath);
var xhr = new XMLHttpRequest();
xhr.open("GET", sPath, 1);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
if (xhr.responseText != "") {
sFileText = xhr.responseText;
//console.log(sFileText);
var val = JSON.parse(sFileText);
var i = 0;
var value = val.length;
for(var i in val)
{
var code = val[i].RTM_res_category_code;
var desc = val[i].RTM_res_category_edesc;
addReserv(code, desc);
}
if(i >= value-1) {
console.log("Reservation Load Completed... "+i);
document.getElementById("status").innerHTML = "Reservation Loading Success...";
}
}
}
}
xhr.send();
}
//Passing Parameters to Reservation
function addReserv(code, desc)
{
document.querySelector("#status").innerHTML = "Loading Reservation.. Please wait...";
var trans = db.transaction(["Reservation"], "readwrite");
var store = trans.objectStore("Reservation");
//console.log(store);
var reserv={ RTM_res_category_code : code, RTM_res_category_edesc : ''+desc+'' };
var request = store.add(reserv);
request.onerror = function(e) {
console.log(e.target.error.name);
document.querySelector("#status").innerHTML = e.target.error.name;
}
request.onsuccess = function(e) {
console.log("Reservation Saved Successfully.");
//document.querySelector("#status").innerHTML = "Reservation Loaded Successfully.";
}
}
Thanks for the question.
What you are currently doing works, but the alert comes to soon because of the async nature of the IDB.
What you should to avoid this.
1. Create your transaction only once.
2. Do all your operations in this one transaction.
3. The transaction object has an oncomplete callback you can use to notify the user.
Concrete on your example. Instead of looping over the items in the ajax callback, pass the collection to your add method and loop there
if (window.XMLHttpRequest) {
var sFileText;
var sPath = "IDBFiles/Reservation.json";
//console.log(sPath);
var xhr = new XMLHttpRequest();
xhr.open("GET", sPath, 1);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
if (xhr.responseText != "") {
sFileText = xhr.responseText;
//console.log(sFileText);
var val = JSON.parse(sFileText);
import(val);
}
}
}
xhr.send();
}
function import(values)
{
document.querySelector("#status").innerHTML = "Loading Reservation.. Please wait...";
var trans = db.transaction(["Reservation"], "readwrite");
var store = trans.objectStore("Reservation");
var i = 0;
var value = val.length;
for(var i in val)
{
var code = val[i].RTM_res_category_code;
var desc = val[i].RTM_res_category_edesc;
var reserv={ RTM_res_category_code : code, RTM_res_category_edesc : ''+desc+'' };
var request = store.add(reserv);
request.onerror = function(e) {
console.log(e.target.error.name);
document.querySelector("#status").innerHTML = e.target.error.name;
}
request.onsuccess = function(e) {
console.log("Reservation Saved Successfully.");
//document.querySelector("#status").innerHTML = "Reservation Loaded Successfully.";
}
}
trans.oncomplete = function () {
console.log("Reservation Load Completed... "+i);
document.getElementById("status").innerHTML = "Reservation Loading Success...";
}
}

How to optimize PhantomJS for search engines to index a single page application?

I have been searching for an headless web browser that can run on server for web crawlers to index a single page application. Firslyt I tried HTMLUnit and Selenium (HtmlUnitDriver) but it seems both of them have issues with xhr requests.
And I discovered PhantomJS which performs better and seems mature. PhantomJS has an internal webserver so I decided to use it with my reverse proxy. However I ran a benchmark and PhantomJS hits a cpu core 100% and the average page loading the is around 4 seconds. The reason is I have to wait the browser to load all resources to be able to get correct results. Here is my PhantomJS script:
var page = require('webpage');
var system = require('system');
var server = require('webserver').create();
// credit: http://backbonetutorials.com/seo-for-single-page-apps/
var service = server.listen(port, { 'keepAlive': true }, function(z, response) {
var request = page.create();
var lastReceived = new Date().getTime();
var requestCount = 0;
var responseCount = 0;
var requestIds = [];
var startTime = new Date().getTime();
request.onResourceReceived = function (response) {
if (requestIds.indexOf(response.id) !== -1) {
lastReceived = new Date().getTime();
responseCount++;
requestIds[requestIds.indexOf(response.id)] = null;
}
};
request.onResourceRequested = function (request) {
if (requestIds.indexOf(request.id) === -1) {
requestIds.push(request.id);
requestCount++;
}
};
request.settings = {
loadImages: false,
javascriptEnabled: true,
loadPlugins: false
};
request.open(z.url, function (status, a) {
if (status !== 'success') {
console.log('FAIL to load the address '+a);
}
});
var checkComplete = function () {
var now = new Date().getTime();
if ((now - lastReceived > 300 && requestCount === responseCount) || now - startTime > 5000) {
clearInterval(checkCompleteInterval);
response.statusCode = 200;
response.headers = {
'Cache': 'no-cache',
'Content-Type': 'text/html; charset=UTF-8',
'Connection': 'Keep-Alive',
'Keep-Alive': 'timeout=5, max=100',
'Content-Length': request.content.length
};
response.write(request.content);
response.close();
request.release();
console.log(request.url+" -> "+(now - startTime));
}
}
var checkCompleteInterval = setInterval(checkComplete, 3);
});
Is there any improvement that can be done to speed up the script, should I just run PhantomJS using its shell command for better performance or is there any alternative to these browsers?
You can use some command line switches to improve the capture performance:
First, you can ignore all images with --load-images=no. There's no need to load images when doing the HTML snapshots.
You can also enable the cache with --disk-cache=yes (use --max-disk-cache-size to set its size in bytes)
Finally, the WebPage#onResourceRequested callback may also be useful to abort some requests (trackers, media files...) with the NetworkRequest#abort method.