Ajax call, function callback, javascript - javascript

I have function like that
function cryptChange(cr){
var url = 'https://min-api.cryptocompare.com/data/dayAvg?fsym=' + cr + '&tsym=PLN';
console.log(url); // it's just for testing in console
};
cryptChange('LTC');
cryptChange('BTC');
As you can see this code is working fine with URL of AJAX call with JSON data, returning valid URL.
Want to make something like that, but in shorter version,
I have many lines of code like the ones below and I do want to get less
$.getJSON('https://min-api.cryptocompare.com/data/dayAvg?fsym=BTC&tsym=PLN', function(btc2){
$('#tt-11').html(btc2.PLN.toFixed(2)); //its passed into html block
});
$.getJSON('https://min-api.cryptocompare.com/data/dayAvg?fsym=BCH&tsym=PLN', function(bch2){
$('#tt-12').html(bch2.PLN.toFixed(2));
});
And now I want to mix that cryptChange function with AJAX call to pass parameter for callback and use that in $ ('#tt-11').html (btc2 here <==.PLN.toFixed (2);
Is that clearer guys now?

Define a function that takes all the varying parts as parameters.
function getCrypt(from, to, id) {
$.getJSON('https://min-api.cryptocompare.com/data/dayAvg', {
fsym: from,
tsym: to
}, function(result){
$('#' + id).html(result[to].toFixed(2));
});
You can then do:
getCrypt('BTC', 'PLN', 'tt-11');
getCrypt('BCH', 'PLN', 'tt-12');

Related

JavaScript static function in callback

Hi I've been trying to clarify this but there's something I'm still confused about. I know that you can't return values from asynchronous functions so I've referenced this answer's top answer Returning value from asynchronous JavaScript method?
What I'm trying to do is use the flickrAPI to get the biggest size image. The flickrAPI allows one to search images, so I use this to get the photo_id, then I use this photo_id to procses another request to the API's getSize method to get the URL for the biggest size photo.
The code looks a little messy as it is, because I have a method called flickrRequest which sends an XMLHttp request and gets back a JSON string. I know that I can achieve what I want by writing the functions as follows:
function flickRQforimage() {
...got ID
function flickrRQforSize() {
...got maxsizeURL
create image based on maxsizeURL here
}
}
but I was wondering if it was possible to do something like this
function flickRQforimage() {
...got ID
function flickrRQforSize() {
...got maxsizeURL
}
create image based on maxsizeURL here
}
or even create image based on maxsizeURL here
In general my question is whether it is possible to have a callback function that references another statically defined function (I think?). The specifics of the my function is that it takes a callback and the ID and URL processing happens in those callbacks:
flickrRQ(options, cb)
I am wondering whether/what would happen if that unnamed function is instead something else, say flickrRQ(options, processPhoto(data)), and then I define the function in a separate method. This just makes sense for me because I want to keep functionality for the URL processing separate in an attempt to make my code cleaner and more readable.
I tried the following below and it didn't work. Nothing prints. I even have a console.log in the processPhoto method. In fact anything inside of the flickrRQforSize method seems to not evaluate
flickrRQforSize(options, function(data) {
processPhoto(data)
}
even though in the flickrRQforSize definition, a callback function is taken as an argument. I'm suspecting there must be something about functions/async calls that I don't understand.
I hope this is clear -- if not, I can post my actual code.
Here's my code:
var flickrRequest = function(options, xhrRQ, cb) {
var url, xhr, item, first;
url = "https://api.flickr.com/services/rest/";
first = true;
for (item in options) {
if (options.hasOwnProperty(item)) {
url += (first ? "?" : "&") + item + "=" + options[item];
//parses to search equest;
first = false;
}
}
//XMLHttpRQ to flickr
if(xhrRQ == 1 ) {
xhr = new XMLHttpRequest();
xhr.onload = function() { cb(this.response); };
xhr.open('get', url, true);
xhr.send();
};
}
var processPhotoSize = function(photoJSON) {
var parsedJSON = JSON.parse(data);
var last = parsedJSON.sizes.size.length;
console.log(parsedJSON.sizes.size[last-1].source);
return parsedJSON.sizes.size[last-1].source;
}
...
flickrRequest(options, 1, function(data) {
...
flickrRequest(sizesOptions, 0, function(data) {
parsedJSON = JSON.parse(data);
console.log(parsedJSON);
processPhotoSize(data);
});
}

Anyway to make this nested callback cleaner?

I'm looking for a way to make this set of AJAX calls cleaner. I've tried using $.when() ...but I could not really get it to work. I think it was due to not passing deferred objects...as my AJAX calls are inside of a model object.
This is what I have thus far (some code was excluded to simply):
var origin_form, destination_form; //assume string input from user
var destination, origin;
getOrigin();
//Gets origin data
function getOrigin(){
//ASYNC CALL
model.searchFeature(origin_form, 1, function(data){
//additional callback code excluded
origin = data;
getDestination();
});
}
//Gets destination information
function getDestination(){
//ASYNC CALL
model.searchFeature(destination_form, 1, function(data){
//additional callback code excluded
destination = data;
directions(origin, destination);
});
}
function directions(origin, destination){
//Async call to request directions from google api
}
Any advice would be great!
Edit: I'm looking for some solution similar to $.when(). Basically, I'd like to call directions() after both getOrigin() and getDestination() are done without having the nested callbacks.
Instead of using a variable in the shared scope, just pass the values from function to function.
var origin_form, destination_form; //assume string input from user
getOrigin();
function getOrigin(){
model.searchFeature(origin_form, 1, getDestination);
}
function getDestination(origin){
model.searchFeature(destination_form, 1, function(data) {
directions(origin, data);
});
}
function directions(origin, destination){
//Async call to request directions from google api
}
Or using Function.prototype.bind, you can clean it up a bit more.
var origin_form, destination_form; //assume string input from user
getOrigin();
function getOrigin(){
model.searchFeature(origin_form, 1, getDestination);
}
function getDestination(origin){
model.searchFeature(destination_form, 1, directions.bind(null, origin));
}
function directions(origin, destination){
//Async call to request directions from google api
}
The first argument passed to .bind() is null because I don't know if you want the this value of directions() to be set. If you do, then replace null with whatever you want this to be.
The answer above by user1689607 gives a good suggestion on how to improve the
callback arrangement.
I think you can further improve this code beyond just making the
callbacks cleaner, however. For one, use camel case and jslint it, then:
// Use a closure/namespace for global abatement
MyNamespace = (function() {
// Use a single 'var' declaration
var originForm,
destinationForm, //assume string input from user
destination,
origin;
function init() {
getOrigin();
}
//Gets origin data
function getOrigin(){
//ASYNC CALL
model.searchFeature(origin_form, 1, function(data){
//additional callback code excluded
destination = data;
getDestination();
});
}
//Gets destination information
function getDestination(){
//ASYNC CALL
model.searchFeature(destinationForm, 1, function(data){
//additional callback code excluded
destination = data;
directions(origin, destination);
});
}
function directions(origin, destination){
//Async call to request directions from google api
}
return {
'init': init
};
}());
MyNamespace.init();

Javascript WinJS.xhr not updating array contents

I am starting out with developing Win8 App with Javascript. I am new to javascript hence I am not too strong with the language. I am trying to parse a json response in my code and store it in an array. Now I want the array to be of objects with particular properties which I am trying to set in the steps of parsing.
But, it seems that the array is not getting updated within the WinJS.xhr portion. To make it more clear, the REF 1(comment in the code below) console output works fine, but REF 2(comment in the code below) console output throws an error as follows:
JavaScript runtime error: Unable to get property 'Name' of undefined
or null reference
var sampleArr = new Array();
WinJS.xhr({ url: "http://some-api-with-json-response" }).then(
function (response) {
var name= JSON.parse(response.responseText);
sampleArr[0] = { Name: name.title };
console.log("First chance:" + sampleArr[0].Name); //REF 1
item_number++;
};
console.log("Second chance:" + sampleArr[0].Name); //REF 2
Can anyone tell, where am I going wrong?
Thanks :)
The problem is that the XHR call is being performed in the background and, while this is happening the JavaScript runtime moves on to the next statement - which is REF2. And so you are trying to read the results of a request before the request itself has completed.
The solution is to put the code that accesses the result in a function which you pass to another call of the then method, like this:
var sampleArr = new Array();
WinJS.xhr({ url: "http://some-api-with-json-response" }).then(
function (response) {
var name = JSON.parse(response.responseText);
sampleArr[0] = { Name: name.title };
console.log("First chance:" + sampleArr[0].Name); //REF 1
item_number++;
}).then(function () {
console.log("Second chance:" + sampleArr[0].Name); //REF 2
});
The function that contains REF2 won't be executed until the function that contains REF1 has completed and that function won't be executed until the XHR request is completed.
.then(callback), the callback function will be executed when the request success.
The code of REF 2 runs before the callback function, at that time, sampleArr[0] is undefined.

display data returned from a javascript/Jquery function

This issue is with jquery.
I have the the following function
$('#admin_id').html(getPartnerName(i, data.admin_id));
And the function getPartnerName is below
function getPartnerName(i, partner_id) {
$.getJSON( '../index.php', 'r=someName&id=1', function(data) {
return data.admin_name;
});
}
I want to print the admin_name returned by json and display it in td with id #admin_id
My code is working fine by not able to display the names.
please help me out to know where am i going wrong.
$.getJSON( '../index.php', 'r=someName&id=1', function(data) {
$('#admin_id').html(data.admin_name);
});
Because the ajax call is asynchronous, you need to provide a callback that is in control of the result parsing; you cannot just return it like from a normal function.
you can assign a variable to the function and call the variable inside html()
Ex:
var output = function getPartnerName(i, partner_id) {
$.getJSON( '../index.php', 'r=someName&id=1', function(data) {
return data.admin_name;
});
}
$('#admin_id').html(output);
hope this is what you were looking for... :)

jQuery ajax function return

I have this function that embeds flash :
function embedswfile(target, swf, base, width, height) {//dosomething}
And I want to call the function like this
embedSwf("flashgame",decode("<?=base64_encode($path['location'])?>"),decode("<?=base64_encode($path['base_directory'])?>"),"800","600" )
The idea is that whenever someone looks for any swf inside my website,he wont find anything clean.I will change the encoding algorithm,but this is just temporary. In order for that function to work,whenever I call the function 'decode' it must return a single value. PHP contains
<?php
echo base64_decode($_POST['s']);
?>
I tried this but it still wont work
var globvar;
function processdata(newmsg) {
globvar = newmsg;
}
function decode(s){
$.ajax({type: "POST",
url: "includes/decode.inc.php",
data: "s=" + s,
success:function(newmsg){
processdata(newmsg);
}
});
return globvar;
}
Important:
Forget about using Ajax and encoding, decoding the path. What do you think you gain from it? Security? No. One can figure out that this is bas64 encoded or he just monitors the network traffic and reads the response from the Ajax call.
Just do
embedSwf("flashgame","<? =$path['location']?>"),"<?=$path['base_directory']?>","800","600" )
Really, you cannot prevent someone else seeing the data and are just making things more complicated for you.
(Or you have to decrypt the data with JavaScript.)
(original answer is still correct nevertheless)
Ajax is asynchronous so something like var test = decode(s); will never work. The decode function will return before the Ajax call finishes.
Instead, put your logic into the callback handler. For example, if your code was this before:
var retdata = decode('s');
// here comes code that handles retdata
put the code into a function and call it from the success handler:
function process(retdata) {
// here comes code that handles retdata
}
function decode(s){
$.ajax({type: "POST",
url: "includes/decode.inc.php",
data: "s=" + s,
success:function(newmsg){
process(newmsg);
}
});
}
This seems to be a very common problem to all beginners. You will find a lot of questions here that deal with the same problem.
Update:
It is not nice, but you could change the function to
function decode(s, cb){
$.ajax({type: "POST",
url: "includes/decode.inc.php",
data: "s=" + s,
success:function(data){
cb(data);
}
});
}
and do
decode("<?=base64_encode($path['location'])?>", function(location) {
decode("<?=base64_encode($path['base_directory'])?>", function(dir) {
embedSwf("flashgame",location,dir,"800","600" );
});
});
Update 2:
For completeness, you can make the Ajax call synchronous, by using async: false. Then this will work:
function decode(s){
var ret;
$.ajax({type: "POST",
url: "includes/decode.inc.php",
data: "s=" + s,
async: false,
success:function(newmsg){
ret = newmsg;
}
});
return sync;
}
var val = decode(s);
However, this will block the browser until the Ajax call finished. You have to test whether this matters in your case or not.
Update 3:
You could also change your PHP script to not only accept one parameter but several and process both strings in one go.

Categories