Store JSON object in a global accessible array [duplicate] - javascript

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
I'm trying to build a function that stores an array of JS objects in a global scope (I want to access this from an external Prototype function). However, when I try to return the 'build' array, the array is undefined (this is probally because I need a proper callback function).
How can I achieve this in a proper way?
function getMyJson(url){
var request = $.getJSON(url);
var items = [];
request.done(function(response) {
for (var key in response) {
if (response.hasOwnProperty(key)) {
var object = {
name: response[key].name,
id: response[key].id
}
items.push(object);
}
}
});
return items; // This returns 'undefined', probally because the for loop is still running
}
var data = getMyJson('data.json');
console.log(data); // undefined
Thanks in advance

As others have mentioned, callbacks are the way to go.
function getMyJson(url, callback){
var request = $.getJSON(url);
var items = [];
request.done(function(response) {
for (var key in response) {
if (response.hasOwnProperty(key)) {
var object = {
name: response[key].name,
id: response[key].id
}
items.push(object);
}
}
callback(items);
});
}
var data = getMyJson('data.json', function(items){
//items will be defined here.
});

Related

Assigning field inside javascript class from ajax [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 4 years ago.
I have code like this:
class Korisnik
{
constructor(korisnikId)
{
this.KORISNIKID = korisnikId;
this.IME = "";
this.UNIQUE_KEY = "";
this.Initialize();
}
Initialize(kid)
{
$.ajax({
type: "POST",
url: "../Php/Korisnik_Get.php",
data: {"korisnikId" : this.KORISNIKID},
success: function(result)
{
var arr = result.split('|');
this.IME = arr[0];
this.UNIQUE_KEY = arr[1];
}
});
}
get naziv()
{
alert("IME: " + this.IME); //Undefined
return this.IME;
}
}
I initialize this class as let myClass = new Korisnik(1);
When I try to get naziv() It returns nothing. I have tested it and when I alert this.IME from inside success code it has value but outside it doesn't. I have read and tried from this question but anything from there is not working for some reason. What to do?
Js getters aren't functions, so you need to access it as myClass.naziv
The other problem you have is that your success function isn't running in the same scope as the rest of your function.
You can use a fat-arrow function to ensure you have the right scope.
success: result =>
{
var arr = result.split('|');
this.IME = arr[0];
this.UNIQUE_KEY = arr[1];
}
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get

JavaScript returning undefined when it's actually defined [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 4 years ago.
My console.log shows the right values, but I can't access my properties!
var subMenus = [], mainMenu = {};
$.getJSON("js/menu.js", function(data){
var menuJsonish = data.MenuEXTERNAL;
//first turn this into an actual array instead of this dumb, non Json stuff
$.each(menuJsonish, function(e) {
var name = e.valueOf();
var eachMenu = [];
if (e != "MenuSettings") { //skip MenuSettings
$.each(menuJsonish[name], function(element) {
var menuArray = [];
$.each(menuJsonish[name][element], function(item) {
var currentItem = menuJsonish[name][element][item];
var k = currentItem[0].valueOf();;
var v = currentItem[1].valueOf();
if (e == 'Menu1') {
eval("mainMenu."+k+" = '"+v+"'");
} else {
eachMenu[k] = v;
}
});
});
if (e != 'Menu1') {
subMenus[e] = eachMenu;
}
}
});
});
// this one returns undefined...
console.log(mainMenu.Menu1);
// yet this one returns all the correct data as shown in the screenshot
console.log(mainMenu);
I don't understand what is going on here. Shouldn't a value be a value? And more importantly, how do I get my data?
I don't think it's necessary to post the entire "JSON" file (which I did NOT create, but I have to work with), but I will post screenshot #2 which shows what it looks like, and why I have to load it like this.

Javascript: Object properties undefined (very specific case) [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
I have a function which is a loop by itself and in this loop I am creating an object. But when after the loop I'm trying to access the object properties, I get an response of undefined.
When I try to just console.log the object itself, I get it. The problem is with properties.
I would be grateful, if someone could help me. I did a good research, but didn't manage to find the solution. My case is very strange. Everything is good except the properties. I need the help of senior developers.
Here is the code.
var countMap = {};
var counter = 0;
$('#share_table_body').find('.js-post').each(function () {
var totalCount = 0;
$(this).find('.js-social').each(function () {
var $this = $(this);
var socialType = $(this).data('social-type');
var url = $this.closest('.js-post').data('url');
getShareStatus(url, socialType)
.then(function (shareCount) {
$this.text(shareCount);
if (!countMap[socialType]) {
countMap[socialType] = 0;
}
if (!countMap['total']) {
countMap['total'] = 0;
}
countMap[socialType] += shareCount;
totalCount += shareCount;
countMap['total'] += shareCount;
$this.siblings('.js-total').text(totalCount);
})
.fail(function (err) {
$('.error-notice').removeClass('hidden');
$this.css('color', 'red').text('!');
});
});
counter++;
});
if (counter == $('#share_table_body').find('.js-post').length) {
console.log(countMap);
$('.total-facebook').text(countMap['facebook']);
}
Are you returning anything from your function? Specifically...
return countMap;

How can I call the second sequential promise design pattern method in a loop in angularjs? [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 6 years ago.
New to angularjs and trying out the promise pattern for the first time -
I have a service utility inside which I have this method -
this.getData= function(url){
var defer = $q.defer();
$http({method: 'GET', url: url}).
success(function(data, status){
defer.resolve(data);
})
.error(function(data, status) {
defer.reject(status);
});
return defer.promise;
};
Now inside my controller, I am calling a method called A()
var A = function () {
$scope.myobjectArray = [];
return utility.getData("some url").then(funciton(data)
{
for (i = 0; i < data.length; i++) {
$scope.myobjectArray.push(data[i].attribute1, new Array());
}
}
).
then(function () {
return getTheSecondAttributeArray();
}).catch(function (status) {
//display error
});
};
var getTheSecondAttributeArray = function () {
for (i = 0; i < $scope.myObjectArray.length; i++) {
var secondAttributeArray = [];
var currentType = $scope.myObjectArray[i];
utility.getData("some url").then(function (response) {
for (j = 0; j < response.length; j++) {
//some response manipulation
secondAttributeArray.push(response[j].text);
}
currentType.secondAttribute = secondAttributeArray;
}).catch(function () {//catch error, display message
})
}
}
However, it looks like that the last element of the $scope.myobjectArray (n-1th element) is only getting populated. Also, the secondAttributeArray that this last element contains is a concatenated array of all secondAttributes for all objects of the $scope.myobjectArray.
Cannot figure out what can I change here.
EDIT:
When I tried accessing $scope.myObjectArray[j] inside the 'then' function, it said $scope.myObjectArray[j] was undefined. --> And so I created a currentType variable and assigned $scope.myObjectArray[j] to it and that was easily accessible inside the 'then' function. Weird!
Also, I see that only the last object of the $scope.myObjectArray gets values and not the rest. The rest of the objects in the array are empty
Any help is appreciated.
var myObject = function(firstattribute, secondAttribute){
this.firstattribute = firstattribute;
this.secondAttribute = secondAttribute;
}
The explanation here by Beehive (Angularjs $q.all) is something that I am facing. I only get the last loop's data.
The issue is all in function closures. When the get data returns, your currentType is the last one because the for j loop ended already. So what you need to do is move the code starting from utility.getData to a separate method passing the parameters of the currentType and the seccondAttributeArray so the closure will contain them as parameters of the function and not change them as the for j loop progresses.
for (i = 0; i < $scope.myObjectArray.length; i++) {
var secondAttributeArray = [];
var currentType = $scope.myObjectArray[i];
fillSecondAttributeArray($scope, secondAttributeArray, currentType);
}

Function sees only three arguments [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 9 years ago.
This is a simplified code that runs on Node.js crawler and it gets all data.
But how do I insert inside the "callback": function value of var "i" from cycle for(var i=0... When I'm adding name: datas[i].name it returns an error:
TypeError: Cannot read property 'undefined' of undefined
var Crawler = require("crawler").Crawler;
var crawler = new Crawler;
var datas = [
{name: 'John', url: 'john025'},
{name: 'Jim', url: 'jim04567'}
];
function crauler(done) {
for (var i = 0; i < datas.length; i++) {
var link = 'http://somesite.com/' + datas[i].url;
crawler.queue([{
"uri": link,
// inside this func
"callback": function (error, result, $, datas, i) {
var arr = $('.blogpost').map(function (index) {
var str = $(this).attr('href');
var object = {
numb: str,
name: datas[i].name
};
return obj;
}).get().join(',');
done(arr);
} }]) }; };
crauler (function (arr) {
console.log(arr);
});
You can't pass datas and i into callback functions like this. What arguments that the callback functions will be called with are up to the caller, you don't have the control of it.
You're seeing "TypeError: Cannot read property 'undefined' of undefined" because you want your callback function to have datas and i as parameters; but the caller will call the callback with the first 3 arguments only [crawler callback reference], so the datas and i are undefined.
Therefore, you should remove the datas and i from in line:
"callback": function (error, result, $, datas, i) {
Because datas is defined in the outer scope of the callback function, the callback can access datas without any special treatment. For the variable i, it's a little bit tricky as mentioned in other answers, so you need to create a closure for it.
So, your callback function definition should be something looks like the following:
"callback": (function(i) { // create closure for i
return function (error, result, $) { // no more datas and i here
var arr = $('.blogpost').map(function (index) {
var str = $(this).attr('href');
var object = {
numb: str,
name: datas[i].name // access datas as it
};
return obj;
}).get().join(',');
done(arr);
}
})(i)
You're trying to create a closure around i inside of a loop which is causing you problems. This answer should help you:
JavaScript closure inside loops – simple practical example
You need a closure to capture the values, this is one way to solve the problem. Read up on closures.
Javascript
var Crawler = require("crawler").Crawler;
var crawler = new Crawler;
var datas = [{
name: 'John',
url: 'john025'
}, {
name: 'Jim',
url: 'jim04567'
}];
function queue(link, i) {
crawler.queue([{
"uri": link,
// inside this func
"callback": function (error, result, $, datas, i) {
var arr = $('.blogpost').map(function (index) {
var str = $(this).attr('href');
var object = {
numb: str,
name: datas[i].name
};
return obj;
}).get().join(',');
done(arr);
}
}]);
}
function crauler(done) {
for (var i = 0; i < datas.length; i++) {
var link = 'http://somesite.com/' + datas[i].url;
queue(link, i);
};
crauler(function (arr) {
console.log(arr);
});

Categories