in my application i want to isolate the Networking in one method , its very common to fetch ajax in my app. so i've put the Ti.Network.createHTTPClient() in a seperate method and i call it with a URL. then it will parse the JSON and return back the result. HOWEVER it always return back a null object.
i'm assuming it retched the end of the method before getting back from the .onload() method
How can i solve that ?
function getJson(url)
{
Ti.API.info(" URL is " + url );
var jsonObject ;
var xhr = Ti.Network.createHTTPClient();
xhr.setTimeout(3000);
xhr.onload = function()
{
var jsonObject = eval('(' + this.responseText + ')');
}
xhr.open("GET" , url);
xhr.send();
Ti.API.info(" passed " );
return jsonObject;
};
You need to set up a callback somewhere in your code like this :
function getJson(url,callback)
{
Ti.API.info(" URL is " + url );
var jsonObject ;
var xhr = Ti.Network.createHTTPClient();
xhr.setTimeout(3000);
xhr.onload = function()
{
callback(jsonObject)
}
xhr.open("GET" , url);
xhr.send();
Ti.API.info(" passed " );
};
function aCallBack(jsonObject){
// the code when the json returns
}
use a callback and give it to your function as a parameter; since it's asynchrone. Like so:
function getJson(url, callback) {
// do your json-ajax stuff
// where you get the response do:
callback(response);
}
function callback(response) {
// do whatever you like with the response
}
Related
I made a REST service, which will return a String "hej" if the log in is true.
I have tested in Java with a rest client and it works fine, but pretty new to javascript and need some help.
I'm using this function
function UserAction() {
console.log(User());
var xhttp = new XMLHttpRequest();
xhttp.open("GET", "http://localhost:8080/Footballmanagerrestservice/webresources/login");
xhttp.setRequestHeader("login", User());
xhttp.responseType = 'text';
xhttp.onreadystatechange = function () {
console.log('DONE', xhttp.readyState);
if (xhttp.readyState == 4) {;
// handle response
var response = xhttp.responseText;
console.log(response);
if (response == "hej") {
var url = "http://localhost:8080/FM3/spil2.jsp";
window.location.href = url;
}
}
};
// send the request *after* the callback is defined
xhttp.send();
return false;
}
function User() {
username = document.getElementById("username").toString();
username = document.getElementById("password").toString();
var UserAndPass = "?username=" + username + "&password=" + password;
return UserAndPass;
}
I show you the client i have i Java, maybe you can see why it's not working.
public static void main(String[] args) {
Client client = ClientBuilder.newClient();
String root="http://localhost:8080/Footballmanagerrestservice/webresources/";
String functionPath="login";
String parameters="?username=s153518&password=holger";
Response res = client.target(root+functionPath+parameters)
.request(MediaType.APPLICATION_JSON).get();
String svar = res.readEntity(String.class);
System.out.println(svar);
}
first part of the code looks ok, the following instead must be handled inside a function because is intrinsically asynchronous
var response = JSON.parse(xhttp.responseText);
console.log(response);
if (response.toString() == "hej") {
var url = "http://localhost:8080/FM3/spil2.jsp";
window.location.href = url
}
return false;
doc: https://developer.mozilla.org/en/docs/Web/API/XMLHttpRequest/onreadystatechange
essentially you're trying to handle the response as a syncrhonous call, but it's not, the response it's not immediatly avaiable, for this reason you have to register a callback (from the doc must be attached to the field onreadystatechange) that will be triggered by javascript as soon as the server response is available.
try to change it like so:
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4) {
// handle response
var response = JSON.parse(xhttp.responseText);
console.log(response);
if (response.toString() == "hej") {
var url = "http://localhost:8080/FM3/spil2.jsp";
window.location.href = url
}
}
}
xhr.send();
I need to build a project to get into a JS bootcamp I am applying for. They tell me I may only use vanilla JS, specifically that frameworks and Jquery are not permitted. Up to this point when I wanted to retrieve a JSON file from an api I would say
$.getJSON(url, functionToPassJsonFileTo)
for JSON calls and
$.getJSON(url + "&callback?", functionToPassJsonPFileTo)
for JSONP calls. I just started programming this month so please bear in mind I don't know the difference between JSON or JSONP or how they relate to this thing called ajax. Please explain how I would get what the 2 lines above achieve in Vanilla Javascript. Thank you.
So to clarify,
function jsonp(uri){
return new Promise(function(resolve, reject){
var id = '_' + Math.round(10000 * Math.random())
var callbackName = 'jsonp_callback_' + id
window[callbackName] = function(data){
delete window[callbackName]
var ele = document.getElementById(id)
ele.parentNode.removeChild(ele)
resolve(data)
}
var src = uri + '&callback=' + callbackName
var script = document.createElement('script')
script.src = src
script.id = id
script.addEventListener('error', reject)
(document.getElementsByTagName('head')[0] || document.body || document.documentElement).appendChild(script)
})
}
would be the JSONP equivalent?
Here is the Vanilla JS version for $.getJSON :
var request = new XMLHttpRequest();
request.open('GET', '/my/url', true);
request.onload = function() {
if (request.status >= 200 && request.status < 400) {
// Success!
var data = JSON.parse(request.responseText);
} else {
// We reached our target server, but it returned an error
}
};
request.onerror = function() {
// There was a connection error of some sort
};
request.send();
Ref: http://youmightnotneedjquery.com/
For JSONP SO already has the answer here
With $.getJSON you can load JSON-encoded data from the server using
a GET HTTP request.
ES6 has Fetch API which provides a global fetch() method that provides an easy, logical way to fetch resources asynchronously across the network.
It is easier than XMLHttpRequest.
fetch(url) // Call the fetch function passing the url of the API as a parameter
.then(res => res.json())
.then(function (res) {
console.log(res)
// Your code for handling the data you get from the API
})
.catch(function() {
// This is where you run code if the server returns any errors
});
Here is a vanilla JS version of Ajax
var $ajax = (function(){
var that = {};
that.send = function(url, options) {
var on_success = options.onSuccess || function(){},
on_error = options.onError || function(){},
on_timeout = options.onTimeout || function(){},
timeout = options.timeout || 10000; // ms
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
//console.log('responseText:' + xmlhttp.responseText);
try {
var data = JSON.parse(xmlhttp.responseText);
} catch(err) {
console.log(err.message + " in " + xmlhttp.responseText);
return;
}
on_success(data);
}else{
if(xmlhttp.readyState == 4){
on_error();
}
}
};
xmlhttp.timeout = timeout;
xmlhttp.ontimeout = function () {
on_timeout();
}
xmlhttp.open("GET", url, true);
xmlhttp.send();
}
return that;
})();
Example:
$ajax.send("someUrl.com", {
onSuccess: function(data){
console.log("success",data);
},
onError: function(){
console.log("Error");
},
onTimeout: function(){
console.log("Timeout");
},
timeout: 10000
});
I appreciate the vanilla js equivalent of a $.getJSON above
but I come to exactly the same point. I actually was trying of getting rid of jquery which I do not master in any way .
What I'm finally strugglin with in BOTH cases is the async nature of the JSON request.
What I'm trying to achieve is to extract a variable from the async call
function shorten(url){
var request = new XMLHttpRequest();
bitly="http://api.bitly.com/v3/shorten?&apiKey=mykey&login=mylogin&longURL=";
request.open('GET', bitly+url, true);
request.onload = function() {
if (request.status >= 200 && request.status < 400) {
var data = JSON.parse(request.responseText).data.url;
alert ("1:"+data); //alerts fine from within
// return data is helpless
}
};
request.onerror = function() {
// There was a connection error of some sort
return url;
};
request.send();
}
now that the function is defined & works a treat
shorten("anyvalidURL"); // alerts fine from within "1: [bit.ly url]"
but how do I assign the data value (from async call) to be able to use it in my javascript after the function was called
like e.g
document.write("My tiny is : "+data);
I am trying to read a local file on the server with a standard function loadDoc(url, cfunc), then
1) search for a particular string in the file (getLine());
2) if possible, store that line to a variable.
For point 1 I pass a string to the callback.
2) Getting the response is problematic because XMLHTTPRequest is asynchronous. At this moment the error is:
"ReferenceError: xhttp is not defined"
function main(){
var url="data.txt"
var str="1,0,"; //just an example
var myCallBackWithVar = function(){
getLine(str);
};
loadDoc(url, myCallBackWithVar);
//Can I get the line here somehow?
}
function loadDoc(url, cfunc) {
var xhttp=new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
cfunc(xhttp);
}
}
xhttp.overrideMimeType('text/plain');
xhttp.open("GET", url, true);
xhttp.send();
}
//Find string with the desired data in txt file
function getLine(str) {
var data=xhttp.responseText;
//Find the line from the txt file
var start=data.indexOf(str);
var end=data.indexOf(";",start);
var line=data.substring(start,end);
return line;
}
data.txt is something like this:
some data here
0,0,9;
1,0,10;
1,1,11;
I have already tried to pass the XMLHTTPRequest objetct getLine(xhttp,str). How to solve points 1 and 2? I'd rather keep it jQuery free for the moment. Thanks
Can I get the line here somehow?
I don't think that's a good idea. You can't be sure that your app will work correctly. XHR is a async function and you should use async architecture.
Here the example how this functionality can be done.
var text; // define global variable
var str = "1,0,"; //just an example
function main(){
var url = "data.txt";
var cb = function (data){
text = getLine(data);
// you can use text var here
// or in anyewhere in your code
}
loadDoc(url, cb);
}
function loadDoc(url, cb) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
cb(xhr.responseText);
}
}
xhr.overrideMimeType('text/plain');
xhr.open("GET", url, true);
xhr.send();
}
//Find string with the desired data in txt file
function getLine(data) {
if(data) {
//Find the line from the txt file
var start = data.indexOf(str);
var end = data.indexOf(";", start);
var line = data.substring(start, end);
return line;
}
}
On complete, you don't need to pass the whole xhttp variable through too the callback function. When you do this:
function getLine(str) {
var data=xhttp.responseText;
xhttp is already out of scope. To fix this, the parameter name would also have to be xhttp.
A better way would be to do :
cfunc(xhttp.responseText);
and then
var data=str
This way, you are passing only what you need as an argument.
In my application i'm isolating the networking in a method and performing a callback to get the JSON response , how can i use it afterward ?
getJson(url, acallback);
function getJson(url, callback) {
Ti.API.info(" im here " + url);
var jsonObject;
var xhr = Ti.Network.createHTTPClient();
xhr.setTimeout(3000);
xhr.onload = function () {
var jsonObject = eval('(' + this.responseText + ')');
callback.call(jsonObject)
}
xhr.open("GET", url);
xhr.send();
Ti.API.info(" passed ");
};
function acallback() {
return this;
}
Now my questions is , how can i use the returned output afterward ?
Should look like this:
function getJson(url, callback) {
Ti.API.info(" im here " + url );
var jsonObject, xhr = Ti.Network.createHTTPClient();
xhr.setTimeout(3000);
xhr.onload = function() {
var jsonObject = JSON.parse(this.responseText);
callback(jsonObject)
}
xhr.open("GET" , url);
xhr.send();
Ti.API.info(" passed " );
}
function acallback(json) {
Ti.API.info("data from ajax: " + json);
}
getJson(url , acallback);
Notice that I removed the use of eval since it's bad practice to use that, as it says (here):
The eval function is very fast. However, it can compile and execute
any JavaScript program, so there can be security issues. The use of
eval is indicated when the source is trusted and competent. It is much
safer to use a JSON parser. In web applications over XMLHttpRequest,
communication is permitted only to the same origin that provide that
page, so it is trusted. But it might not be competent. If the server
is not rigorous in its JSON encoding, or if it does not scrupulously
validate all of its inputs, then it could deliver invalid JSON text
that could be carrying dangerous script. The eval function would
execute the script, unleashing its malice.
Also, you better use the var keyword only once per scope.
Edit
If you want to use the resulting json object from outside the scope of the callback, just define the callback in the scope where the json is needed, for example:
var obj = {
x: 4,
doit: function() {
var _this = this;
var callback = function(json) {
alert(_this.x * json.y);
};
getJson(url , callback);
}
}
The json.y part I just made up for the example of course.
2nd Edit
Alternatively, if you want to use the call option, you can do this:
function getJson(url, callback, bindto) {
Ti.API.info(" im here " + url );
var jsonObject, xhr = Ti.Network.createHTTPClient();
xhr.setTimeout(3000);
xhr.onload = function() {
var jsonObject = JSON.parse(this.responseText);
callback.call(bindto, jsonObject)
}
xhr.open("GET" , url);
xhr.send();
Ti.API.info(" passed " );
}
var obj = {
x: 5
}
function myCallback(json) {
alert(this.x * json.y);
}
getJson(url, myCallback, obj);
3rd Edit
If we're on the subject, I recommend using a nice trick, which is used in Prototype, MooTools, jQuery and according to the MDN was Introduced in JavaScript 1.8.5.
Function.prototype.bind = function(scope) {
var _function = this;
return function() {
return _function.apply(scope, arguments);
}
}
You can read the tutorial where I copied to code from.
The code that needs to use the output should be placed in acallback (or placed in a function that's called from acallback).
I believe callback.call(jsonObject) should actually read callback(jsonObject). Once you have invoked an asynchronous function, the way to get its value is via a callback. So, the function you pass in as callback will get the result. Say,
function myCallback(value) {
console.log(value);
}
function get_request(url) {
var request = new getXMLObject();
request.onreadystatechange = function () {
if (request.readyState == 4) {
alert(request.responseText);
var data = eval('(' + request.responseText + ')');
alert(data);
return data;
}
}
request.open("GET", url, true);
//alert(document.getElementById('energy').innerHTML);
request.send();
}
function loadjobs() {
var url = "loadjobs.php?tab=1&id=1111";
//var data=
//alert(check());
alert(get_request(url));
//alert(data);
}
When i m getting data in json format...i am gettin NULL in alert(get_request(url));
while i m getting in alert(data);
Help me
This is because the request in asynchronous . The get_request(url) function does to return anything and hence the null ( although I think it should be undefined and not null ) .
The onreadystatechange function gets called later in the time , when the AJAX request has been completed and the data is returned from the server and hence the alert there works .
This is a misunderstanding of how AJAX works. Ajax is asynchronous. The onreadystatechange function will be called after loadjobs(). The "return path" you are specifying can never work. get_request() will never be able to return the fetched value.
You have two options. Either make the script synchronous - this can be done but is not recommended because it can freeze the browser.
Or, better, handle everything you need to do inside the onreadystatechange callback.
Well, it's an asynchronous call. You will receive the data of request your after get_request has already returned. That means your request.onreadystatechange = function () will be executed long after alert(get_request(url)); is already finished. This means get_request will not be able to return any data from the AJAX call. That's what you have the request.onreadystatechange callback function for, to execute code at an undefined later time when you received the response.
The problem is that Ajax requests work asynchronously. So you can't return the data right away. The way you should do it is to specify a callback function which will handle the response data.
function handleJSON( data ) {
// ...
// do whatever you want to do with the data
}
ajax( "url/file.php?param=value", handleJSON );
////////////////////////////////////////////////////////////////////////////////
function getXmlHttpObject() {
var xmlHttp;
try {
xmlHttp = new XMLHttpRequest();
} catch (e) {
try {
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
}
return xmlHttp;
}
function ajax(url, onSuccess, onError) {
var xmlHttp = getXmlHttpObject();
xmlHttp.onreadystatechange = function () {
if (this.readyState == 4) {
// onError
if (this.status != 200) {
if (typeof onError == 'function') {
onError(this.responseText);
}
}
// onSuccess
else if (typeof onSuccess == 'function') {
onSuccess(this.responseText);
}
}
};
xmlHttp.open("GET", url, true);
xmlHttp.send(null);
return xmlHttp;
}