Javascript Variable not updating/saving [duplicate] - javascript

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
How can I save information locally in my chrome extension?
(2 answers)
Closed 5 years ago.
I have a string which I need in multiple functions. Therefore I want to save it in a variable. But when I try to assign it inside a function it doesn't update the variable.
var auth_code = "na";
function safeAuthCode(authcode){
auth_code = authcode;
console.log(auth_code);
}
"auth_code" prints just fine in the console at that point, but when I try to use it later it just contains "na". Not sure what I'm doing wrong tbh :/
Edit:
This is the function in which safeAuthCode is called:
function auth(){
chrome.identity.launchWebAuthFlow({
"url": "https://accounts.spotify.com/authorize?client_id="+client_id+
"&redirect_uri="+ encodeURIComponent(redirectUri) +
"&response_type=code"+
"&scope=" + encodeURIComponent(scopes),
"interactive": true
},
function(redirect_url) {
var url = new URL(redirect_url);
var code = url.searchParams.get("code");
safeAuthCode(code);
});
}

I am assuming that the problem you are having is because of the global variable that either gets overwritten in a different part of the code, or because your code at a certain point in time reloads, and the initial value gets reset.
To save such authentication code, you could make use of the sessionStorage object of your browser.
To make sure you only have 1 such object, you could use the const keyword to define your variables (in case another definition of that variable would come at a later time, you should get an error thrown)
const authorisationSettings = {
get code() {
return sessionStorage.getItem('authorisationCode') || 'na';
},
set code(value) {
return sessionStorage.setItem('authorisationCode');
}
};
function saveAuthorisationCode( code ) {
authorisationSettings.code = code;
}
saveAuthorisationCode( 'test' );
console.log( authorisationSettings.code );
This snippet doesn't work on stackoverflow, so you can find the jsfiddle here

It happens because of when your function is executed, in lexical environment of that function is already exist authcode variable and you are trying to set this one instead of global authcode
You need to change name of global variable or param of the fuction...

Related

How to resolve asynchronous variable? [duplicate]

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 1 year ago.
I am trying to get a shared key based on whether it already exists in the db or not. I am using Firebase store database.
The problem is that even though i assign passkey some value inside the sub-function, when I do console.log outside the function, it just prints the original passkey which was set at declaration.
I have tried using window.passkey and window.global.passkey by declaring passkey as global variable, outside all functions, but it didn't work.
I am working with a node.js project. My code is as follows:
// var passkey = {"shared_key":""} // Declaring passkey as global variable but didn't work.
const onSubmit = (formData) => {
const email_id = getUserDetails().email;
const from_db = db.collection(email_id);
const to_db = db.collection(formData.to);
var passkey = {"shared_key": ""};
// Check if there exists a shared key between `from` and `to`
// Checking for shared key in either of the db is enough.
to_db.doc(email_id).get().then((res) => {
// assume that res.exists is true.
if (res.exists) {
passkey.shared_key = res.data().shared_key; // passkey is set here
} else {
// Generate and use a shared key
...some code to generate a shared key ...
passkey.shared_key = generated_key;
}
});
console.log(passkey);
// above prints {"shared_key": ""} instead of printing the value of shared key taken from the database.
// or the one that is generated!
};
I know it is related to variable hoisting in javascript but I think there has to be some workaround.
Any help/comment is appreciated. Thanks in advance.
When you code with this pattern
function doIt () {
var something = ''
invokeFunction()
.then (function handleResult (result) {
console.log('2', something)
something = result
} )
console.log('1', something)
}
your console.log('1', something) runs before the inner function (I named it handleResult for clarity) is ever called. That's because invokeFunction() is asynchronous; it returns a Promise object.
You could rewrite this as follows:
async function doIt () {
var something = await invokeFunction()
console.log('1', something)
}
to get the kind of result you want.
With respect, you will have a very hard time coding Javascript unless you take the time to learn about async / await and Promises. In that respect the Javascript language is very different from other languages. Drop everything and learn that stuff now. Seriously.

PhantomJS: call a user defined/custom function within phantomjs [duplicate]

This question already has an answer here:
Cannot pass module functions to Page
(1 answer)
Closed 6 years ago.
i'm getting a ReferenceError when i call a function i defined myself inside the page.evaluate() of Phantom; what is the proper way to do that ?
for example:
function mySweetFunction(item) {
// process item....
}
page.evaluate(function(){
var item= document.getElementsById('item');
mySweetFunction(item);
});
then i'll get the error:
ReferenceError: Can't find variable: mySweetFunction
What is the proper way to do this ?
mySweetFunction is quite big, and i would prefer to keep it out of page.evaluate(...) if possible.
If you want to use a function inside page.evaluate() you have to put it there first:
page.evaluate(function(){
function mySweetFunction(item) {
// process item....
}
var item = document.getElementsById('item');
mySweetFunction(item);
});

Understanding variable scope and closures with JavaScript callback functions [duplicate]

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 been stuck for far too long on the following problem that I really need to consider my theoretical knowledge about variable scope and callback functions in Javascript. Rather than a quick fix for my particular problem a generalized answer that tries to explain the theory behind my problem is preferred. Here is the code (that doesn't work) (oh and it uses jQuery's $.getJSON).
function getStreamerStatus(streamer) {
var channelurl = "https://api.twitch.tv/kraken/channels/";
var streamurl = "https://api.twitch.tv/kraken/streams/";
var temporary = {
status: "",
game: "",
picture: "",
name: streamer,
link: "https://www.twitch.tv/" + streamer
};
$.getJSON(streamurl + streamer, createCallback(temporary));
$.getJSON(channelurl + streamer, createCallback(temporary));
return temporary;
}
After some searching I used the "createCallback()" function in an attempt to make the "temporary" object visible to the callback function.
function createCallback(tmpobj) {
return function(json) {
//get's some information and stores it in the object passed as tmpobj
filterOut(json, tmpobj);
};
}
And in the end in the main function I have an array with names of twitch streamers and for each name the "getStreamerStatus()" function is called and the returned object is stored in an array.
function TwitchInit() {
var channels = [/*filled with strings of streamer names*/];
var response = []; //array with objects with all the information
for(var i = 0; i < channels.length; i++) {
response.push(getStreamerStatus(channels[i]));
}
parseContent(response); //not relevant for now
//for debugging
for(var j = 0; j < response.length; j++) {
console.log("--responseArray with Objects--");
for(var prop in response[j]) {
if(response[j].hasOwnProperty(prop)) {
console.log(prop + ": " + response[j][prop]);
}
}
}
}
The problem here is that if I log the objects to the console only the "link" and "name" properties of the objects have some content and the other properties who're supposed to be written by the "filterOut()" function always remain empty. According to the console the communication with the Twitch server is fine and I can read the response header/object from the console so that rules out. And since the "name" and "link" properties are also different at each log to the console that means that each time a new object is created which is fine. That leads me to the conclusion that the "temporary" object still somehow isn't visible to the callback function inside $.getJSON despite my attempt with "createCallback()" to make the object visible to the "filterOut()" function. I have found a lot of information about variable scope in JavaScript but so far it hasn't helped my to solve my problem. I have no clue what I am doing wrong here and I'm starting to get frustrated. I really hope someone can enlighten me here.
I think there is no problem is closure here, the only problem is that your getStreamerStatus function will perform async tasks but will return a value directly, and use it without waiting the async calls (getJSON) to complete.
Try to put you debug logs inside a setTimeout with few seconds delay ;)
To so things better you should rewrite your getStreamerStatus to only returns the data after the getJSON calls are done, not before, with a callback as parameter, or by returning a promise.
Or you should have something (ie: an event) to tell your function that the calls are finished, and that it can process the results.

Updating global variable: 1. Using member function vs. 2. Using AJAX callback function [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
Background:
I'm building a simple program that uses the simpleWeather.js API to pull in the current temperature to be used by the rest of the program (http://simpleweatherjs.com/).
Updated Code:
All the below code is within an AngularJS controller and the simpleWeather.js file is linked in the index.html file.
var _this = this;
var seasons = null;
function myAjaxCheck(callBack){
$.simpleWeather({
location: 'Calgary, CA',
woeid: '',
unit: 'c',
success: function(weather) {
var temperatureTemp = parseInt(weather.temp);
callBack(temperatureTemp);
}
});
}
var temperature;
myAjaxCheck(function(returnedTemperature){
temperature = returnedTemperature;
if (temperature > 20){
_this.seasons = summerCollection; <-- summerCollection is an array strings
}
});
Alternative that works:
var _this = this;
var seasons = null;
var test = function(){
_this.seasons = summerCollection;
};
test();
UPDATE: Problem:
It seems that I can update the global variable with the member function test() as in the 2nd snippet of code. However, why isn't the global variable updated with the AJAX callback function in the 1st snippet of code?
I have a div in my HTML that uses ng-repeat to spit out all the strings in the summerCollection array.
It works with the 2nd snippet of code but does not with the first.
Any help is greatly appreciated!
Any ideas?
Original Problem:
From what I gathered from the web inspector, it appears that the order in which this code loads is (which it should not):
a. $.simpleWeather({...
b. alert(temperature)
c. success: function(weather){...
Any ideas why this is? I know that if I put alert(temperature) in the success:function(weather){} then it'll return the current temperature but this is not what I want.
I ultimately want the variable temperature to hold the current temperature so that I can use this variable in other functions. For instance, I want to be able to set "seasons" to different strings according to the temperature value.
Any help is greatly appreciated!
Well this is the nature of callbacks - they are asynchronous. The code is supposed to run in the order you described.
And what you're doing is correct, except that the alert is running BEFORE your callback is complete (as it should).
So what you need to do is put your alert (and the real code that you want to run), into the callback:
var temperature = null; <-- this variable should store the temperature retrieved by simpleWeather API
var seasons = null;
$.simpleWeather({
location: 'Calgary, CA',
woeid: '',
unit: 'c',
success: function(weather) {
temperature = parseInt(weather.temp); <-- Temperature variable defined outside this scope
alert(temperature);
// call your remaining code here, which will run after the temperature has been set.
some_other_function();
}
});
function some_other_function() {
}

variables in $.get() function: can't access out of that function again? [duplicate]

This question already has answers here:
Get var out of jQuery.get nested function
(2 answers)
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
I have another javascript/jQuery's variables scope questions to ask...
Say I declared a object named Container. In which there is a variables called myimage which will read a address from some xml file.
Container = function()
{
var myimage;
}
Container.prototype.readXML = function()
{
$.get("assest/xml/images.xml",function(xml)
{
//Read in URL path from XML file, and store them into memeber variables
myimage = $(xml).find('background').text();
//Apply background image into body, and apply css styple into it
$("body").css('background-image','url(' + myimage + ')');
//This alert will work
alert(myimage);
});
//This alert gives not defined variable
alert(myimage);
}
Please look at the two alert section. It seems this variable I defined in the Container object, can only work inside that readXML function. but not out. I can't understand why this happend.
I do use some other notation, like declare with
this.myimage
and access it by change name of this to self before execute the $.get function
var self= this;
But it get worse. Sometimes it even can't be reached anymore inside the get function.
Could you help me with this? My final goal is an array in that object and read bunch of data from XML than display them into HTML. If the variables I set in the Object can't be reached, there is no way I can do that.
Thank you!!
Container = function()
{
var myimage;
}
should most likely be defined as below. More importantly, $.get is asynchronous so you cannot assume it finishes each line of code in the order it's written.
var Container = function()
{
this.myimage = '';
}
Container.prototype.readXML = function(callback) {
$.get("assest/xml/images.xml", function(xml) {
//Read in URL path from XML file, and store them into memeber variables
this.myimage = $(xml).find('background').text();
//Apply background image into body, and apply css styple into it
$("body").css('background-image', 'url(' + this.myimage + ')');
//This alert will work
callback(this.myimage);
});
}​
var instance = new Container();
instance.readXML(function (copy) {
alert(copy);
});​
All variables in Javascript that are not declared in the global scope are local to the function they are declared in.
Since functions are objects in Javascript, you can assign properties to them. So, you can do
Container.myimage = $(xml).find('background').text();
//...
alert(Container.myimage);

Categories

Resources