This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 5 years ago.
I want to store the length of a Json array as a global variable to make my code more modular. I am trying to set the global variable inside the .onload function but it won't allow this. I have tried with a globalTest variable.
var objectLength = 0;
var globalTest = 0;
$(document).ready(function() {
establishConnection();
});
function establishConnection() {
xttp = new XMLHttpRequest();
xttp.open("GET", "http://exampleServerPath", true);
xttp.send("null");
xttp.onload = function() {
var Json = JSON.parse(this.response);
objectLength = Json.length;
globalTest = 2; // this doesn't work
};
globalTest = 4; //this works
}
I am fairly new to JS any help is appreciated!
I think the issue lies with the xttp.onload part. Change that to xttp.onreadystatechange and then check the readystate.
Check out this example.
EDIT:
Your code works as expected, but maybe you think globalTest is not being updated.
If you were to call establishConnection() and then immediately try to access globalTest it will still be 0 because the AJAX request has not completed yet.
If you did
establishConnection();
setTimeout(function() {
alert(globalTest);
}, 2000);
Then you should see the value you expect (assuming your ajax request completes in less than 2 seconds.
Related
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
I am setting a url to a DOM of a website. Now I could done it by copying the actual url, as below:
document.getElementById('mediaWebUrl').setAttribute('value','https://www.youtube.com/watch?v=hkOTAmmuv_4');
It is not convenient enough. I want to substitute the actual url with a variable. like below:
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
var activeTab = tabs[0];
var videoUrl = activeTab.url; // or do whatever you need
});
But when I do the job as below:
document.getElementById('mediaWebUrl').setAttribute('value',videoUrl);
it didn't succeed and nothing happened. Why? I confirmed the type of the variable "videoUrl" is a string using alert(typeof videoUrl). As neophyte in Javascript, I really need advice in this simple question. Thank you.
You can write a function and pass the value of the id of the div (where you want to display the video) and the video url, and then call the function to set the attribute.
Sample code:
function setVal(id, val){
var el = document.getElementById(id); //get the element
var attrVal = val; //set the url
el.setAttribute('value', val) //set the value to the url
}
setVal("myVid", "https://www.youtube.com/watch?v=hkOTAmmuv_4"); //call the function
(in this case, myVid is the id)
Your code probably didn't worked because the variable was only locally defined.
You can use your web console to check for errors.
Hope this helps!
This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Iterate array and wait for promises
(1 answer)
Closed 4 years ago.
While I have been working in python for quite some time, I've recently started working with javascript for its tight integration with Web.
I am still struggling with concepts of event driven programming and promise driven function.
Anyway, Below I am using node.js module is-port-reachable.
It does a good job of returning status if given host is reachable over a given port or not.
However, I need to collect combined info of host and port status.
For e.g. if I have hosts = ['hostA' , 'hostB' ];
I need to collect status of its port scan status as
hosts2 = [ ('hostA' , true) , ('hostB', false)];
With below code, I am able to get individual status of port scan for each host, but when I try to add it to array host2, its coming back as empty.
It seems promise function is not able to take/recognize external variable aHost.
const isPortReachable = require('is-port-reachable');
hosts = [ 'host' , 'host2'];
var hosts2 = new Array();
for ( var l = 0; l < hosts.length; l++) {
var aHost = hosts[l];
const myFunction = (aHost) =>{
return isPortReachable(8443, {host: aHost})
};
myFunction(aHost).then(result => {
console.log(aHost, result);
hosts2.push((aHost,result));
});
}
console.log(hosts2);
Output:
Further, Looks like console.log(hosts2); is getting executed before for loop.
node myscript.js
[]
hostA true
hostB false
Any help is appreciated.
I'm currently writing a search function using JavaScript.
However, when I attempt to test my creation, I find that it stops about halfway through for no discernible reason.
Below is my code:
document.getElementById("test").innerHTML = "";
var Connect = new XMLHttpRequest();
Connect.open("GET", "xmlTest.xml", false);
document.getElementById("test").innerHTML = "1";
Connect.send(null);
document.getElementById("test").innerHTML = "2";
var docX = Connect.responseXML;
var linjer = docX.getElementsByTagName("linjer");
The first line is there to clear a potential error message from earlier in the code. Then I attempt to open up an XML file, as I need to read from it.
As you can see, I've entered two debug statements there; they will print 1 or 2 depending on how far I get in the code.
Using this, I've found that it stops exactly on the Connect.send(null); statement (as 1 gets printed, but 2 never does), but I can't figure out why. Google says that it might be that chrome can't access local files, but when I found a way to allow Chrome to do this, it still did not work.
What am I doing wrong?
This might be a synchronous issue that requires a response that your code simply is not getting.
Try using an async call instead:
Connect.open("GET", "xmlTest.xml", true);
Also make sure to setup proper callbacks since you'll be using async here now instead of synchronous code, like so:
// Global variable scope
var docX;
var linjer;
// Define your get function
getDoc = function(url, cbFunc) {
var Connect = new XMLHttpRequest();
// Perform actions after request is sent
// You'll insert your callback here
Connect.onreadystatechange = function() {
// 4 means request finished and response is ready
if ( Connect.readyState == 4 ) {
// Here is where you do the callback
cbFunc(Connect.responseXML);
}
};
// 'true' param means async, it is also the default
Connect.open('GET', url, true);
Connect.send();
}
// Define your callback function
callbackFunction = function(responseXML) {
// XML file can now be stored in the global variable
window.docX = responseXML;
window.linjer = window.docX.getElementsByTagName("linjer");
}
// And here is the call you make to do this
getDoc("xmlTest.xml", callbackFunction);
For better understanding of all of this, do some research on scope, closures, callbacks, and async.
In my javascript application I have big memory leak when making AJAX call to retrieve JSON object. Code is really simple:
function getNewMessage()
{
new_message = []; // this is global variable
var input_for_ball = [];
var sum;
var i;
var http = new XMLHttpRequest();
http.open("GET", url + "/random_ball.json", false);
http.onreadystatechange = function()
{
if(http.readyState === 4 && http.status === 200)
{
var responseTxt = http.responseText;
input_for_ball = JSON.parse('[' + responseTxt + ']');
}
}
http.send(null);
new_message = input_for_ball;
}
This is called every 1 milisecond and as you see, its synchronous call. This function costs me 1MB every 1 second.
When I use instead of AJAX just assigning to variable like:
input_for_ball = JSON.parse('[0,0,0,0,0,0,0,0,0,0]');
then its everything perfect. So error must be in my implementation of AJAX call. This happened when I use jQuery AJAX call too.
UPDATE 12/03/2013
As Tom van der Woerdt mentioned below, this really was intended behavior. So as Matt B. suggested, I have rewrote some code to make asynchronous calls possible and it helped a lot. Now my application memory consuming is stable and small.
I don't think it's the AJAX call, but the closure which is costing you memory. Your onreadystatechange function references the http object (so a reference to this will be kept with the anonymous function).
I think your code matches the pattern in example 1 in this link http://www.ibm.com/developerworks/web/library/wa-memleak/
If you've not come across closures in javascript before, they're well worth reading up on - understanding them explains a lot of behaviour which doesn't seem to make sense at first glance.
This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 6 years ago.
I'm sure my problem is based on a lack of understanding of asynch programming in node.js but here goes.
For example: I have a list of links I want to crawl. When each asynch request returns I want to know which URL it is for. But, presumably because of race conditions, each request returns with the URL set to the last value in the list.
var links = ['http://google.com', 'http://yahoo.com'];
for (link in links) {
var url = links[link];
require('request')(url, function() {
console.log(url);
});
}
Expected output:
http://google.com
http://yahoo.com
Actual output:
http://yahoo.com
http://yahoo.com
So my question is either:
How do I pass url (by value) to the call back function? OR
What is the proper way of chaining the HTTP requests so they run sequentially? OR
Something else I'm missing?
PS: For 1. I don't want a solution which examines the callback's parameters but a general way of a callback knowing about variables 'from above'.
Your url variable is not scoped to the for loop as JavaScript only supports global and function scoping. So you need to create a function scope for your request call to capture the url value in each iteration of the loop by using an immediate function:
var links = ['http://google.com', 'http://yahoo.com'];
for (link in links) {
(function(url) {
require('request')(url, function() {
console.log(url);
});
})(links[link]);
}
BTW, embedding a require in the middle of loop isn't good practice. It should probably be re-written as:
var request = require('request');
var links = ['http://google.com', 'http://yahoo.com'];
for (link in links) {
(function(url) {
request(url, function() {
console.log(url);
});
})(links[link]);
}
Check this blog out. A variable can be passed by using .bind() method. In your case it would be like this:
var links = ['http://google.com', 'http://yahoo.com'];
for (link in links) {
var url = links[link];
require('request')(url, function() {
console.log(this.urlAsy);
}.bind({urlAsy:url}));
}
See https://stackoverflow.com/a/11747331/243639 for a general discussion of this issue.
I'd suggest something like
var links = ['http://google.com', 'http://yahoo.com'];
function createCallback(_url) {
return function() {
console.log(_url);
}
};
for (link in links) {
var url = links[link];
require('request')(url, createCallback(url));
}