This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 7 years ago.
I am trying to pass two values to a function from two async functions and I am not sure how to proceed. Here is the code:
var btcPriceInUSD;
var priceExchangeMXN;
var btcLink = "https://blockchain.info/ticker";
var exchangeRateLink = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.xchange%20where%20pair%20in%20%28%22USDMXN%22%29&env=store://datatables.org/alltableswithkeys&format=json";
//Get btc price in USD
$.getJSON(btcLink, function(btcData)
{
btcPriceInUSD = btcData.USD.last;
//document.write(btcPriceInUSD);
});
//Get current USD/MXN exchange rate
$.getJSON(exchangeRateLink, function(exchangeData)
{
priceExchangeMXN = exchangeData.query.results.rate.Rate;
//document.write(priceExchangeMXN);
});
//Convert btc price to MXN
function convertToMXN(btc,toMXN){
var result = parseFloat(btc) * parseFloat(toMXN);
document.write(result);
}
convertToMXN(btcPriceInUSD,priceExchangeMXN)
I know the issue is that I am calling the function outside of the async ones so it is not recieving the numbers and it is giving me a NAN (not a number) but I don't know how I would correctly pass those two parameters that are each retrieved in different functions, is it possible to combine the btcPriceInUSD and priceExchangeMXN in one and call it from there?
Thanks in advance!
Try using $.when() , .then() , substituting returning value at complete function for declaring variables outside scope of asynchronous functions ; also adding an error handler
$.when($.getJSON(btcLink, function(btcData) {
return btcData.USD.last
})
, $.getJSON(exchangeRateLink, function(exchangeData) {
return exchangeData.query.results.rate.Rate
}))
.then(convertToMXN, function err() {console.log(arguments)})
try this (simply chaining the ajax calls and finally calling the method when both values are available)
var btcPriceInUSD;
var priceExchangeMXN;
var btcLink = "https://blockchain.info/ticker";
var exchangeRateLink = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.xchange%20where%20pair%20in%20%28%22USDMXN%22%29&env=store://datatables.org/alltableswithkeys&format=json";
//Get btc price in USD
$.getJSON(btcLink, function(btcData)
{
btcPriceInUSD = btcData.USD.last;
//document.write(btcPriceInUSD);
//Get current USD/MXN exchange rate
$.getJSON(exchangeRateLink, function(exchangeData)
{
priceExchangeMXN = exchangeData.query.results.rate.Rate;
//document.write(priceExchangeMXN);
convertToMXN(btcPriceInUSD,priceExchangeMXN);
});
});
//Convert btc price to MXN
function convertToMXN(btc,toMXN){
var result = parseFloat(btc) * parseFloat(toMXN);
document.write(result);
}
Related
This question already has answers here:
JS replace not working on string [duplicate]
(2 answers)
Closed 7 months ago.
So, I was trying to create e encryption app, the app should take the value of the input and use the replace function to change the letters to the words that I specified in the function trocaLetras, but it just returns undefined in the console log.
This is my code:
var botaoCriptografar = document.querySelector('#criptografar');
function trocaLetras(conteudoInput) {
conteudoInput.replace(/a/g, 'ai');
conteudoInput.replace(/e/g, 'enter');
conteudoInput.replace(/i/g, 'imes');
conteudoInput.replace(/o/g, 'ober');
conteudoInput.replace(/u/g, 'ufat');
}
botaoCriptografar.addEventListener('click', function(event){
event.preventDefault();
var texto = document.querySelector('#texto-para-coleta').value;
var textoAtualizado = trocaLetras(texto);
console.log(textoAtualizado);
});
<textarea id="texto-para-coleta"></textarea>
<button id="criptografar">Criptografar</button>
The replace function will actually not change the value in the variable, but instead returns a string with the replaced characters. So you must chain multiple calls of replace.
Also your function needs to return the result. So your function works if you change it to this:
function trocaLetras(conteudoInput) {
return conteudoInput.replace(/a/g, 'ai')
.replace(/e/g, 'enter')
.replace(/i/g, 'imes')
.replace(/o/g, 'ober')
.replace(/u/g, 'ufat');
}
two issues here
.replace doesn't change the original variable value. so if you do
let s = 'some';
s.replace('some', 'else');
console.log(s); // 'some'
so your function needs to reassign the value, or you can create a new one.
javascript function needs explicit returns, so if you don't return anything, it'll show up as undefined.
function trocaLetras(conteudoInput) {
conteudoInput = conteudoInput.replace(/a/g, 'ai');
conteudoInput = conteudoInput.replace(/e/g, 'enter');
conteudoInput = conteudoInput.replace(/i/g, 'imes');
conteudoInput = conteudoInput.replace(/o/g, 'ober');
conteudoInput = conteudoInput.replace(/u/g, 'ufat');
return conteudoInput;
}
const botaoCriptografar = document.getElementById('button');
botaoCriptografar.addEventListener('click', function(event){
event.preventDefault();
var texto = document.querySelector('#texto-para-coleta').value;
var textoAtualizado = trocaLetras(texto);
console.log(textoAtualizado);
});
<button id='button'>Encrypt</button>
<input id="texto-para-coleta" />
JavaScript - Calculating values using numeric results from separate functions and display without user interaction.
I’m looking to calculate the percentage difference between returned API values (extracted from a single target API, but different ‘GET’ URL’s) and display the percentage differential.
I’m using separate functions to extract each value as the ‘GET’ URL is time stamped to perform searches for specific results.
Ive included only 2 functions, but would like to calculate the difference between more as required.
I’ve only included the Javascript, if there is a typo in the code, then it is only a typo, the functions display the relevant data, it is calculating the percentage difference between “BTC_Result_Now” (from the 1st function) and BTC_Result_1_Week (from the 2nd function) that proving not so straight forward:
var BTC_XHR_Now = new XMLHttpRequest();
function getBTC_Price_Now() {
var url = BTC_API_PriceNow;
BTC_XHR_Now.open('GET', url, true,);
BTC_XHR_Now.onload = function() {
var response = JSON.parse(BTC_XHR_Now.responseText);
var BTC_Result_Now = response.BTC.USD;
document.getElementById("BTC-Price-Now").innerHTML = BTC_Result_Now; // $17077.13
}
BTC_XHR_Now.send();
}
getBTC_Price_Now();
var BTC_XHR_1_Week = new XMLHttpRequest();
function getBTC_Price_1_Week() {
var url = BTC_API_Price1Week;
BTC_XHR_1_Week.open('GET', url, true,);
BTC_XHR_1_Week.onload = function() {
var response = JSON.parse(BTC_XHR_1_Week.responseText);
var BTC_Result_1_Week = response.BTC.USD;
document.getElementById("BTC-Price-1-Week").innerHTML = BTC_Result_1_Week; // $13749.57
}
BTC_XHR_1_Week.send();
}
getBTC_Price_1_Week();
So, three small parts:
1) a MaxMind geo IP lookup that gets us the country code via the IP address:
var onSuccess = function(x){
var ip = x.traits.ip_address;
document.getElementById('ip_address').value = ip;
var country_code = x.country.iso_code;
document.getElementById('ip_country_code').value = country_code;
…
};
2) an array of country references with tax percent decimals:
// Array of values for tax rates
var tax_rates= new Array();
tax_rates["noteu"]=0.0;
tax_rates["ES"]=21.0;
tax_rates["AU"]=20.5;
tax_rates["BE"]=21.7;
…
3) a TaxPrice function that takes one of those decimals to calculating tax and then total payable in a subscription form. Notice the XXXXX:
function TaxPrice()
{
var taxprice=0;
XXXXX
return taxprice;
}
The document.getElementById bit in 1) can obviously update a hidden field or some other HTML element.
I know what to do with XXXXX if it's a manual drop down the user has to select.
But how do I get the tax decimal out of the array and into the TaxPrice function based on the IP address country code? (i.e. within the javascript, not updating an HTML element).
Happy New Year to all.
UPDATE: Just to be clear, I don't need to know how to get it into a drop down, I can do that already and in this use case, the user should not be allowed to choose his own tax country, it should be set automatically based on the IP address. So the non-code wording would go something like:
taxprice EQUALS tax_rate.value ACCORDING TO ip_address_code
Are you looking for something like element properties?
Mydiv.tax=taxvalue;
Properties of Elements are an elegant way of communicating between different functions.
You can assign any value to any element.
You can retrieve the value from any function in JavaScript as long as the Basic element lives.
One way you can do it is to set a global selectedCountryCode variable inside your success callback, and reference tax_rates[selectedCountryCode] in your TaxPrice array (which should be an object, as nnnnnn pointed out)
(function () {
var selectedCountryCode = "";
var onSuccess = function(x) {
var ip = x.traits.ip_address;
document.getElementById('ip_address').value = ip;
selectedCountryCode = x.country.iso_code; // <-- Set selectedCountryCode for later use
document.getElementById('ip_country_code').value = selectedCountryCode; // <-- Set dropdown value
};
document.getElementById("ip_country_code").addEventListener("change", function() {
selectedCountryCode = this.value;
console.log(TaxPrice());
});
// Object of values for tax rates
var tax_rates = {};
tax_rates["noteu"] = 0.0;
tax_rates["ES"] = 21.0;
tax_rates["AU"] = 20.5;
tax_rates["BE"] = 21.7;
function TaxPrice() {
var taxprice = 0;
taxprice = tax_rates[selectedCountryCode];
return taxprice;
}
})();
Change Me: <select id="ip_country_code">
<option value="noteu">noteu</option>
<option value="ES">ES</option>
<option value="AU">AU</option>
<option value="BE">BE</option>
</select>
So, thanks for your suggestions. Not sure if I understand how this is working exactly, but after some poking around, it now is. Compared to the code in the original question, I had to:
1) Add a global variable at the top, above everything else, unrelated to the IP lookup code (i.e. there is now no reference to country_tax within the IP onSuccess variable):
var country_tax;
2) Replace XXXXX in the TaxPrice function with:
var country_tax = document.getElementById("ip_country_code").value;
var taxprice = taxes_from_database[country_tax];
So the full TaxPrice function ends up as:
function TaxPrice()
{
var taxprice = 0;
var country_tax = document.getElementById("ip_country_code").value;
var taxprice = tax_rates[country_tax];
return taxprice;
}
No need, it seems, for nested functions or closures or anything very complicated. It doesn't matter (to the code) if the tax_rates are set up as an array or an object, the outcome is the same, although I would like to understand why you recommend an object over an array in this case.
And—given TaxPrice gets the value from the form field and not from within the IP onSuccess function—I don't know why I need the global variable declaration at the top, if anyone wants to have a go at explaining that…
This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 6 years ago.
I have various products in a drop down list. If I change the product, then the price changes and the line cost changes commensurate with the quantities being ordered.
Problem: When I select a product, an Ajax call is made to my DB. The correct price is returned. All good. When I choose an alternative product from the drop down, the product ID and it's var value changes correctly. However,instead of returning the new correct price, priceshows the value from the previous query. That is to say, it appears that either the price is being cached, or the arraydata[0].price is not being cleared or the Ajax call is failing. I do not believe that the Ajax call is failing, as if I make then a further product change, I get a new result, BUT, again the price value from the query preceding it. Bottom line, my price is always one query behind. I have tried using cache:false but that has made difference. I also tried setting the length of the variable result to 0, that just delivered an undefined error.
$(".product_id").on('change', function() { //THIS GETS THE VALUE OF A PRODUCT FROM THE DB
var value = parseFloat($(this).val()); // product_id
var row = $(this).parents(':eq(1)').find('input').filter(".cost");
var rowPrice = $(this).parents(':eq(1)').find('input').filter(".price");
// then we use the product_id to grab the price using AJAX //
$.ajax({
type: 'GET',
url: 'product_prices/' + value,
cache:false,
success: function(data) {
data = JSON.parse(data);
var result = data[0].price;
var price = Number(result); //.toFixed(2);
row.data('price', price); // store the row's current price in memory
rowPrice.val(price); // allocate the price to the location called rowPrice
}
});
var quantity = $(this).parents(':eq(1)').find('input').filter(".quantity").val();
if (quantity > 0){
var price = row.data('price');
var cost = (price * quantity);
cost = Number(cost); //.toFixed(2);
var displaycost = $.formatNumber(cost,{format:"#,###.00",locale:"ca"});
row.val(displaycost);
var subTotal = 0;
$("input.cost").each(function(){
var ic = $(this).val();
if (ic !==''){
var inputCost = parseFloat(ic.replace(/,/g, ''));
subTotal += inputCost;}
});
var discount_percent = $("#discount").val();
if(discount_percent ==""){
discount_percent = 0;
}
var calculations = newCalculate(subTotal, discount_percent);
setValues(calculations, $("#updateValues"));
}
});
Ajax calls are asynchronous, meaning the callback function that you provide for it, is only executed later. In your case this means that this statement:
row.data('price', price);
is executed later (asynchronously) than this one:
var price = row.data('price');
...which indeed means you set the price to the previously retrieved value.
To avoid that, you'll probably want to move most of your code into the success callback function provided to $.ajax(), so that it only gets executed when you actually have received the data with the price.
This question already has an answer here:
variable scope in d3 javascript
(1 answer)
Closed 7 years ago.
I have a global variable say :
var series,hours;
var loadData = function(){
series = [[]];
hours = [];
d3.json("data/radar.json", function(error, data) {
data.QualitySummaryObject.forEach(function(d,i) {
series[i] = d.extractPercentage;
hours[i] = d.extractorName;
});
});
console.log(hours);
};
Now if I am trying to access this console.log its working fine, but.
var print = function(){
console.log(hours); //here its not working no value in hours why ... ?
}
Ensure that you hours is global:
window.hours = [];
Then anywhere you can log it:
console.log(window.hours);
Using directly var without declaration will avoid context problems.
If you are running the above code in a function, the variable hours is not a global variable because you previously declared it with var.
If you want to declare a variable as a global variable, instead of this:
var hours = [];
Do this:
hours = [];
To declare a global variable, all you have to do is give it a name.