Unexpected Uncaught TypeError [duplicate] - javascript

This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
This code is an external file, test.js, which is linked to from index.html, after the jQuery file.
When I refresh my browser and go into the console, I get this error message:
Uncaught TypeError: Cannot read property 'starshipName' of undefined
on line 20, where I try to alert the starshipName property of the first item in the array.
var starships = [];
function starship(starshipName, model, manufacturer) {
this.starshipName = starshipName;
this.model = model;
this.manufacturer = manufacturer;
}
function starshipData(data) {
for (i = 0; i < data.results.length; i++) {
var results = data.results[i];
starships.push(new starship(results["name"], results["model"], results["manufacturer"]));
}
}
$.getJSON('https://swapi.co/api/starships/', function(data) {
starshipData(data);
});
alert(starships[0].starshipName);
However, when I type out the last line of code or log the starships array to the console, it works perfectly. I am very confused as to why this is happening and will appreciate any help! Thank you in advance.

$.getJSON is an asynchronous function. This means that your alert() is called before starships is filled with data - hence the undefined property error.
All operations that depend on an async function must be placed in, or called from, the callback. Try this:
$.getJSON('https://swapi.co/api/starships/', function(data) {
starshipData(data);
// 1: place the call in the callback
// 2: always use console.log to debug as it does not coerce data types
console.log(starships[0].starshipName);
});

Related

Javascript Variable not updating/saving [duplicate]

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...

exctracting a variable from a jquery method [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
I want to extract the variable response from the mentionsInput() method and using it outside this method, but when I try an alert() on this variable it's empty.
jQuery(document).ready(function() {
var choix = $('#choixaide').val();
var choix_sous_theme1 = $('#choix_sous_theme1aide').val();
$('textarea.mention1').mentionsInput('val', function(text) {
var response = text;
});
alert(response);
});
Thanks for your help.
As you have it now, response is only available within the scope of your mentionsInput method, but not outside of it.
Additionally, when running your code, I see the following error:
Uncaught TypeError: $(...).mentionsInput is not a function"...
Are you sure you've properly loaded the jquery.mentionsInput UI component? You'll need to solve for this error first, if you are also encountering this.
Then, you'll need to declare the variable response prior to and outside of your mentionsInput method, and then set it within mentionsInput. The value set for response should then be available in the same scope as your alert call.
I think this should do the trick:
jQuery(document).ready(function() {
var choix = $('#choixaide').val();
var choix_sous_theme1 = $('#choix_sous_theme1aide').val();
var response = $('textarea.mention1').val();
alert(response);
});

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.

Javascript: Function overwrite with passing arguments [duplicate]

This question already has answers here:
Passing arguments forward to another javascript function
(5 answers)
Closed 8 years ago.
I am using Winston (Logger for nodejs).
In my script i call:
log.error("my error", {input: [1,2]});
console show me:
error: my error input=[1, 2]
What i want to do: don' call at log.error(null)
In some functions i dynamically call the log.error with a variable and dont know if the variable are NULL or have a value. If i call log.error(null) he write "error:" to the console.
I tried with this:
log.error = (function () {
var old = log.error;
return function newerror() {
if (arguments.length !== 0) {
old(arguments);
}
};
})();
But now i got:
error: 0=my error, input=[1, 2]
as output.
My Question
how i can call the log.error() function with die arguments given (arguments-var in javascript is a object).
Function style:
function foo(arg1,arg2,...)
I want something like:
foo.call(myargumentsobj);
oh i got it:
old.apply(this, arguments);

Categories

Resources