JavaScript seemingly unable to access object property [closed] - javascript

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 5 years ago.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Improve this question
So I have this object, Looks like this:
I am trying to access the when_is_meeting property. I dont have any issue accessing any other property in this object. But if I try to access when_is_meeting I get an undefined as seen above next to "WHEN IS IT"
This is what the code looks like....
var listOfObjects = [];
for (var modelData in responseData) {
listOfObjects.push(service.create(name, responseData[modelData]));
console.log('RESP', response.data.content[modelData]);
console.log('WHEN IS IT!!!',response.data.content[modelData].when_is_meeting);
}
Does anyone know what the heck is going on here? Did I spell something wrong? I've been over it 50 times. Must be something simple im overlooking.
----------------EDIT------HERE IS THE WHOLE SERVICE----------------------
service.fetch = function (name, id, options) {
options = options || {};
const ModelClass = service.models[name];
const baseUrl = ModelClass.getUrl(service.getBaseUrl(ModelClass), ModelClass.getModelName());
let url;
let paged = false;
let pageList = false;
if (id) {
if (id instanceof models.BaseModel) {
const BaseModelModelName = id.getModelName();
let baseModelWithId = ModelClass.getUrl(service.getBaseUrl(), BaseModelModelName);
url = [baseModelWithId, id.getId(), ModelClass.getModelName(), ''].join('/');
pageList = true;
} else {
url = [baseUrl, id].join('/');
}
} else {
pageList = true;
url = [baseUrl, ''].join('/');
}
if (options.path) {
url = url + options.path;
delete options.path;
}
if (typeof options.paged === 'object') {
let currentPage = options.paged.page;
let pageSize = options.paged.page_size || 20;
paged = options.paged;
options.page = currentPage;
options.size = pageSize;
if (options.paged.sort) {
let sortParam = options.paged.sort;
options.sort = sortParam.param+','+sortParam.order;
}
delete options.paged;
}
return AuthRequestsService.load.then(function () {
return $http({
method: 'GET',
url: url,
headers: {
'Authorization': AuthRequestsService.getAuthorizationHeader(),
},
params: options,
json: true
});
}).then(function (response) {
console.log('RESPONSE',response);
for (let i = 0; i < response.data.content.length; i++){
if (response.data.content[i].activity_history_type == 3){
let builder = JSON.parse(response.data.content[i].relations);
let secondaryUrl = AppSettings.apiUrl + ['/advisor/meetings', builder.meeting].join('/');
$http({
url: secondaryUrl,
headers: {
'Authorization': AuthRequestsService.getAuthorizationHeader(),
},
method:'GET',
json:true,
}).then(function(res){
response.data.content[i].when_is_meeting = res.data.meeting_date;
console.log('WHEN IS',response.data.content[i].when_is_meeting); // <-- this works
})
}
}
if (!pageList) {
return service.create(name, response.data);
} else {
let responseData = response.data;
if (paged) {
responseData = response.data.content;
}
var listOfObjects = [];
for (var modelData in responseData) {
listOfObjects.push(service.create(name, responseData[modelData]));
console.log('RESP', response.data.content[modelData]);
listOfObjects[modelData].when_is_meeting = response.data.content[modelData].when_is_meeting;
listOfObjects[modelData].whatever = 44;
console.log('response.data.content[modelData].when_is_meeting',response.data.content[modelData].when_is_meeting);
console.log('listOfObjects[modelData].when_is_meeting', listOfObjects[modelData].when_is_meeting);
console.log('listOfObjects[modelData].whatever', listOfObjects[modelData].whatever);
console.log('Keys', Object.keys(response.data.content[modelData]));
// console.log('PRE IF', response.data.content[modelData].when_is_meeting);
// listOfObjects[modelData].when_is_meeting = response.data.content[modelData].when_is_meeting;
// console.log('IFFFFFFFFFFFFFFFFFFFFF', listOfObjects[modelData].when_is_meeting);
// console.log('IN FOR LOOP RESP', response.data.content[modelData].when_is_meeting);
// console.log('listOfObjects[modelData] PART 2', listOfObjects[modelData]);
function testForKey() {
if (typeof response.data.content[modelData].when_is_meeting !== "undefined") {
// when_is_meeting now exists! Do stuff with it here.
console.log("We now have the key:", response.data.content[modelData].when_is_meeting)
}
else {
// when_is_meeting is still missing. Try again in 200ms.
window.setTimeout(testForKey, 200);
console.log('TTTIIMMMEEEEOOOUUUTTT');
}
}
testForKey();
}
if (paged) {
console.log('#########################', listOfObjects);
return {
objects: listOfObjects,
totalPages: response.data.totalPages,
currentPage: response.data.number,
isMore: (!response.data.last),
totalElements: response.data.totalElements
};
} else {
return listOfObjects;
}
}
});
};

This problem occurs because when you expand the toggle to view an object the console show what it has now, not what it had at the time it was logged.
This is explained well here: http://felix-kling.de/blog/2011/08/18/inspecting-variables-in-javascript-consoles/
This scenario is not uncommon when you are working with Ajax. You are trying to access the result before everything has completed; ie, something else in your code is working on your response.data and adding in the missing key after your console.log statements.
This is confirmed by the logging statement suggested in the comments above by #Steven. Object.keys(response.data.content[modelData])) will show the keys available at the time the log statement is made and hence does not have the same problem as just logging the object itself to the console. The results from that confirm when_is_meeting is indeed missing at log-time.
To fix this properly, we need to see more of your code so we can work out why you are trying to access your result before other things finish using it.
Or you can do a crude workaround using timeouts to test the response.data.content[modelData] for the availability of when_is_meeting and only access it when it exists, like the example below. But this is not really recommended - much better to figure out where the problem lies in your response handling.
var listOfObjects = [];
for (var modelData in responseData) {
listOfObjects.push(service.create(name, responseData[modelData]));
// testForKey looks for the required key 'when_is_meeting' and if it does not
// exist it starts a timeout to test for it again in the future.
function testForKey() {
if (typeof response.data.content[modelData].when_is_meeting !== "undefined") {
// when_is_meeting now exists! Do stuff with it here.
console.log("We now have the key:", response.data.content[modelData].when_is_meeting)
}
else {
// when_is_meeting is still missing. Try again in 200ms.
window.setTimeout(testForKey, 200);
}
}
testForKey();
}
(I've not tested this code - it might have syntax errors)
Update - a fix for your supplied code
Your supplied code shows that as predicted the when_is_meeting key is being added to your result in a separate Ajax call. This call complete asynchronously and as such its result is not available to your log statements below it. This fragment shows one approach for fixing it. As before, I have not syntax-checked this code.
return AuthRequestsService.load.then(function () {
return $http({
method: 'GET',
url: url,
headers: {
'Authorization': AuthRequestsService.getAuthorizationHeader(),
},
params: options,
json: true
});
}).then(function (response) {
console.log('RESPONSE',response);
for (let i = 0; i < response.data.content.length; i++){
if (response.data.content[i].activity_history_type == 3){
let builder = JSON.parse(response.data.content[i].relations);
let secondaryUrl = AppSettings.apiUrl + ['/advisor/meetings', builder.meeting].join('/');
// Store the result of this $http call as a promise.
response.data.content[i].when_is_meeting_promise = $http({
url: secondaryUrl,
headers: {
'Authorization': AuthRequestsService.getAuthorizationHeader(),
},
method:'GET',
json:true,
})
// Remove your .then handler from here. It will be dealt with below.
//.then(function(res){
// response.data.content[i].when_is_meeting = res.data.meeting_date;
// console.log('WHEN IS',response.data.content[i].when_is_meeting); // <-- this works
//})
}
}
if (!pageList) {
return service.create(name, response.data);
} else {
let responseData = response.data;
if (paged) {
responseData = response.data.content;
}
var listOfObjects = [];
for (var modelData in responseData) {
// OK, now access the promise you stored above. This means you'll be sure you'll
// have the when_is_meeting key.
responseData[modelData].when_is_meeting_promise.then(function(when_is_meeting_result) {
// Now you can copy the neeting date into your responseData object.
responseData[modelData].when_is_meeting = when_is_meeting_result.data.meeting_date;
// Carry on....
listOfObjects.push(service.create(name, responseData[modelData]));
console.log('RESP', response.data.content[modelData]);
// This should now work...
console.log('response.data.content[modelData].when_is_meeting',response.data.content[modelData].when_is_meeting);
});
}
}
});

Related

Having trouble console.log anything from this API, we're not allowed to use JQuery or Bootstrap, so I have to use fetch and bulma

so I've been having trouble trying to get anything to console.log from this API, the most I can get is a null or undefined return. I've tried just the base statement from the API company, and the code snippet runs for them but for some reason won't even return a console.log for me. not sure if it's a problem on their end or mine because it seems to run fine on their website. also as I said in the title, I have to use fetch
EDIT: I'm in coding school right now so I'm pretty new to all of this
EDIT: the dashboard shows that the API is being called, so why am I not getting any responses?
EDIT: I figured it out, the API wasn't working
// global variables
var countryInput = document.querySelector("#ipt-country");
var submitButton = document.querySelector("#submit-btn");
var currencyDisplay = document.querySelector("#currency-display");
// country currency array codes
var countryCurrencyArray =[ list off all countries with iso code for currency goes here, not going to list it bc its 270 lines long
];
// begins exchange rate function
function getExchangeRate() {
// grab data attribute
var countrySearch = countryInput.value.toLowerCase().trim();
var currencyUSA = "USD";
var countryCurrency = "AUD";
// var countryCurrency = countryInput.value.countryCurrencyArray[i];
// if else errors
if (countrySearch.length < 1) {
return(null);
} else {
var countryConversion = countryCurrencyArray.find(
(element) => element.name === countrySearch)
}
if (countryConversion === void 0) {
return(null);
} else {
var countryCurrency = countryConversion.code;
}
// fetch API to change currency rate from American Dollar (USD) to selected currency
fetch(
'https://currency-converter5.p.rapidapi.com/currency/convert?' +
'&from=' + currencyUSA +
'&to=' + countryCurrency +
'&amount=1',
{
"method": "GET",
"headers": {
"x-rapidapi-host": "currency-converter5.p.rapidapi.com",
"x-rapidapi-key": "API-KEY"
},
}).then(response => {
console.log(response);
})
.then(function(response) {
response.json().then(function(data){
for (i=0; i < data.response.countryCurrency.length; i++) {
var exchangeMoney = document.createElement("div");
exchangeMoney.classList.add(
"is-flex-mobile",
"column",
"has-text-centered",
"is-justify-content-space-evenly"
);
var exchangeOutput = document.createElement("div");
exchangeRateOutput.classList.add("level-item");
exchangeRateOutput.innerText = data.response.countryCurrency[i].code;
exchangeRateMoney.appendChild(exchangeOutput);
console.log(exchangeOutput);
}
});
}).catch(err => {
console.error('Request Failed', err);
});
}
getExchangeRate();
console.log(getExchangeRate());
submitButton.addEventListener("click", getExchangeRate);

Get all items or data from API where they need to meet a condition to be fetched

I want to display a list of all items or data from an API source where the VirtualOrganization (or some other data) is the one i specify (like ATCclub). I use Axios to get the data.
Baicicly I only want to only fetch the JSON data from the API where the VirtualOrganization is the right one, and then display it.
Here is my code:
let data;
axios.get(URLBASE + '/flights/' + expert + '?apikey=' + APIKEY, {
params: {
virtualOrganization: "ATCclub"
}
})
.then(response => {
console.log(response.data.result);
if (response.data.result.virtualOrganization === "ATCclub") {
for (let i = 0; i < response.data.result.virtualOrganization.array.length; i++) {
document.getElementById("username").innerHTML = response.data.result.username;
document.getElementById("aircraftId").innerHTML = response.data.result.aircraftId;
document.getElementById("heading").innerHTML = response.data.result.heading;
document.getElementById("latitude").innerHTML = response.data.result.latitude;
document.getElementById("longitude").innerHTML = response.data.result.longitude;
document.getElementById("speed").innerHTML = response.data.result.speed;
document.getElementById("altitude").innerHTML = response.data.result.altitude;
}
}
})
.catch(error => console.error(error));
NOTE: I have managed to display one row from the JSON.
I found a solution after someone sent me a answer to "filter it after".
Then I came up with this:
// resF (result of flights)
const resF = response.data.result.filter(function (e){
return e.virtualOrganization === "ATCclub";
});

Angular delete - API is not receiving the call [duplicate]

This question already has answers here:
Angular 2 http get not getting
(4 answers)
Closed 3 years ago.
I have the following auto-generated code (NSwag Studio) - the only amendment is withCredentials which I've added for Windows Auth (intranet app).
deleteObjective(id: number): Observable<ObjectiveDTO> {
let url_ = this.baseUrl + "/api/Objectives/{id}";
if (id === undefined || id === null)
throw new Error("The parameter 'id' must be defined.");
url_ = url_.replace("{id}", encodeURIComponent("" + id));
url_ = url_.replace(/[?&]$/, "");
let options_ : any = {
observe: "response",
responseType: "blob",
withCredentials: true,
headers: new HttpHeaders({
"Accept": "application/json"
})
};
return this.http.request("delete", url_, options_).pipe(_observableMergeMap((response_ : any) => {
return this.processDeleteObjective(response_);
})).pipe(_observableCatch((response_: any) => {
if (response_ instanceof HttpResponseBase) {
try {
return this.processDeleteObjective(<any>response_);
} catch (e) {
return <Observable<ObjectiveDTO>><any>_observableThrow(e);
}
} else
return <Observable<ObjectiveDTO>><any>_observableThrow(response_);
}));
}
everything else in the generated service works fine (this is the only delete) but this is literally not sending any traffic - in the Chrome Network pullout (F12) there is no call to the API and the API does not receive anything.
I am calling it from my component like this:
deleteObjective(): void {
if (confirm('Are you sure you want to delete this objective? This cannot be un-done.')) {
if (this.objective.id !== 0)
this.service.deleteObjective(this.objective.id);
for (var i = 0; i < this.objectives.length; i++) {
if (this.objectives[i] === this.objective) {
this.objectives.splice(i, 1);
}
}
}
}
and the splice is definitely working. If I put debugger before the http request it calls it. There are no errors in the console.
Any ideas? I am new to angular but old to programming.
When you are calling the function from the service, make sure you subscribe() to it.
The API will be hit only after you subscribe
Try like this:
deleteObjective(): void {
if (confirm('Are you sure you want to delete this objective? This cannot be un-done.')) {
if (this.objective.id !== 0)
this.service.deleteObjective(this.objective.id).subscribe(res => {
for (var i = 0; i < this.objectives.length; i++) {
if (this.objectives[i] === this.objective) {
this.objectives.splice(i, 1);
}
}
})
}
}

Associative array not filling up in server-sent-event environement

I think I'm on the wrong track here:
I have an event source that gives me updates on the underlying system oprations. The page is intended to show said events in a jquery powered treetable. I receieve the events perfectly but I realized that there were a case I did not handle, the case where an event arrives but is missing it's parent. In this case I need to fetch the missing root plus all potentially missing children of that root node from the database. This works fine too.
//init fct
//...
eventSource.addEventListener("new_node", onEventSourceNewNodeEvent);
//...
function onEventSourceNewNodeEvent(event) {
let data = event.data;
if (!data)
return;
let rows = $(data).filter("tr");
rows.each(function (index, row) {
let parentEventId = row.getAttribute("data-tt-parent-id");
let parentNode = _table.treetable("node", parentEventId);
// if headless state is not fully
// resolved yet keep adding new rows to array
if (headlessRows[parentEventId]) {
headlessRows[parentEventId].push(row);
return;
} else if (parentEventId && !parentNode) { // headless state found
if (!headlessRows[parentEventId])
headlessRows[parentEventId] = [];
headlessRows[parentEventId].push(row);
fetchMissingNodes(parentEventId);
return;
}
insertNode(row, parentNode);
});
}
function fetchMissingNodes(parentEventId) {
let url = _table.data("url") + parentEventId;
$.get(url, function (data, textStatus, request) {
if (!data)
return;
let rows = $(data).filter("tr");
//insert root and children into table
_table.treetable("loadBranch", null, rows);
let parentNode = _table.treetable("node", parentEventId);
let lastLoadedRow = $(rows.last());
let headlessRowsArray = headlessRows[parentEventId];
while (headlessRowsArray && headlessRowsArray.length > 0) {
let row = headlessRowsArray.shift();
let rowId = row.getAttribute("data-tt-id");
if (rowId <= lastLoadedRow) // already loaded event from previous fetch
continue;
insertNode(row, parentNode);
let pendingUpdatesArray = pendingUpdates[rowId];
// shouldn't be more than one but who know future versions
while (pendingUpdatesArray && pendingUpdatesArray.length > 0) {
let updateEvent = headlessRowsArray.shift();
updateNode(updateEvent)
}
delete pendingUpdates[rowId]; // <- something better here?
}
delete headlessRows[parentEventId]; // <- something better here too?
});
}
The problem is around the line if (headlessRows[parentEventId]).
When I run it step by step (putting a debugger instruction just before) everything works fine, the headless array is created and filled correctly.
But as soon as I let it run full speed everything breaks.
The logs I printed seems to indicate that the array is not behaving in the way I was expecting it to. If I print the array with a console.log it shows as follow :
(2957754) [empty × 2957754]
length : 2957754
__proto__ : Array(0)
It seems to be missing any actual data. whereas it shows as follow when I execute it step by step:
(2957748) [empty × 2957747, Array(1)]
2957747:[tr.node.UNDETERMINED]
length:2957748
__proto__:Array(0)
I'm missing something but it is still eluding me.
your code is async, you do http request but you treat him as synchronized code.
try this fix
//init fct
//...
eventSource.addEventListener("new_node", onEventSourceNewNodeEvent);
//...
async function onEventSourceNewNodeEvent(event) {
let data = event.data;
if (!data)
return;
let rows = $(data).filter("tr");
rows.each(function (index, row) {
let parentEventId = row.getAttribute("data-tt-parent-id");
let parentNode = _table.treetable("node", parentEventId);
// if headless state is not fully
// resolved yet keep adding new rows to array
if (headlessRows[parentEventId]) {
headlessRows[parentEventId].push(row);
return;
} else if (parentEventId && !parentNode) { // headless state found
if (!headlessRows[parentEventId])
headlessRows[parentEventId] = [];
headlessRows[parentEventId].push(row);
await fetchMissingNodes(parentEventId);
return;
}
insertNode(row, parentNode);
});
}
function fetchMissingNodes(parentEventId) {
return new Promise((resolve,reject) =>{
let url = _table.data("url") + parentEventId;
$.get(url, function (data, textStatus, request) {
if (!data){
resolve()
return;
}
let rows = $(data).filter("tr");
//insert root and children into table
_table.treetable("loadBranch", null, rows);
let parentNode = _table.treetable("node", parentEventId);
let lastLoadedRow = $(rows.last());
let headlessRowsArray = headlessRows[parentEventId];
while (headlessRowsArray && headlessRowsArray.length > 0) {
let row = headlessRowsArray.shift();
let rowId = row.getAttribute("data-tt-id");
if (rowId <= lastLoadedRow) // already loaded event from previous fetch
continue;
insertNode(row, parentNode);
let pendingUpdatesArray = pendingUpdates[rowId];
// shouldn't be more than one but who know future versions
while (pendingUpdatesArray && pendingUpdatesArray.length > 0) {
let updateEvent = headlessRowsArray.shift();
updateNode(updateEvent)
}
delete pendingUpdates[rowId]; // <- something better here?
}
delete headlessRows[parentEventId]; // <- something better here too?
resolve()
});
})
}

Need to loop again depending on a condition javascript

Hi I'm making a javascript script which now is getting really hard to edit, and hard to understand for other people, I'll put it here hoping someone can understand it and give some advice or help
function fetchMember(id, select, sitename, total) {
return function() {
progress();
$.ajax({
type: 'POST',
url: "script.php",
data: $("#fetch").serialize() + "&id=" + id,
success: function(data) {
isUser = ($(data).text().indexOf("Invalid User") == -1);
if (isUser) {
username = $(data).find(".normal").text();
saved = id - invalid;
$.ajax({
type: 'POST',
url: "save.php",
data: {'username': username},
success: function(data) {
$("#test").append(id+" "+data + "<br />");
select.text(sitename+"("+saved+"/"+total+")"); //Updating numbers of fetched profiles on the frontend
}
});
}
else
invalid++; //loop again here because a user wan't valid
progress();
}
});
}
}
for (i = 0; i < members; i++) {
fetched++;
setTimeout(fetchMember(fetched, select, sitename, total), wait*i);
}
basically what I need to do is to loop again if at the end of the operation there are some invalid users, any help is really appreciated
I wonder if this code would help you, though it's not completely adapted for your case and wasn't tested. The main principle is the recursive call of memberFetch function. No need for timeouts in this case - it won't make any new requests to the server until it got a response for the last one. Feel free to ask any questions, but please try to experiment yourself :)
var currentId = 0; // Current member id
var membersNum = 10; // There are 10 members from 0 to 9
var neededValidUsersNum = 5; // We need only 5 valid users...
var valudUsersNum = 0; // ... but now we have 0 of them
// Let's make an array of all possible id's
// It will be a queue - we will try to fetch the first id
// In case of success - save data, remove that id from the queue, fetch the nex one
// Otherwise - put it at the back of the queue to try it again later
var possibleIds = [];
for (var i = 0; i < membersNum; i++) {
possibleIds.push(i);
}
// Fetched user data storage
var userData = {};
function fetchMember(id) {
var data = "some data";
$.post('script.php', data)
.done(function(responseData){
onFetchMemberDone(id, responseData);
})
.fail(function(){
onFetchMemberFail(id);
});
}
function onFetchMemberDone(id, responseData){
// Save recieved user data
userData[id] = responseData;
// Bump valid users num
valudUsersNum++;
// If there are not enough valid users - lets continue:
if (valudUsersNum < neededValidUsersNum) {
// Remove valide user from the queue (it was the first one)
possibleIds.shift();
// try to fetch the next one
var nextPossibleId = possibleIds[0];
fetchMember(nextPossibleId);
}
}
function onFetchMemberFail(id){
// add failed user to the end of the queue
possibleIds.push(id);
// try to fetch the next one
var nextPossibleId = possibleIds[0];
fetchMember(nextPossibleId);
}
// Lets launch the cycle! It doesn't look like one because it works through recursive calls
onFetchMember(0);

Categories

Resources