Cannot read property 'vehicle_full' of undefined - javascript

When I am loading my app I am getting this js exception. Not sure why!
Uncaught (in promise) TypeError: Cannot read property 'vehicle_full'
of undefined at ActionCreators.js:?
export function loadPairDataActionCreator(address, refresh, topPartner, bottomPartner) {
return dispatch => fetch(address, returnHeaders())
.then(res => checkLogout(res))
.then(
data => {
// Change primary key from SHA to cName
if (data) {
let nd = [];
for (let p in data) {
const pair = data[p];
let tmp = {};
const pair_ids = Object.keys(pair);
for (let pi of pair_ids) {
tmp[pair[pi].vehicle_full] = pair[pi];
}
nd.push(tmp);
}
data = nd;
store.dispatch(currentPairs(data));
let vehicles = store.getState().vehicles,
keys = Object.keys(vehicles);
for (var i = 0; i < data.length; i++) {
const pair = data[i];
// pair ids
const [vehicle1, vehicle2] = Object.keys(pair);
// Add pairedWith field to each truck in the pair
store.dispatch(
addPairedVehicleActionCreator(
pair[vehicle2].vehicle_full, //<--- error here
vehicle1
))
store.dispatch(
addPairedVehicleActionCreator(
pair[vehicle1].vehicle_full,
vehicle2
))
}
store.dispatch(pairingComplete(true))
}
},
err => dispatch({
type: 'LOAD_PAIR_DATA_FAILURE',
err
})
)
.then(
() => {
if (refresh === "unpair") {
store.dispatch(changePageModeActionCreator({
mode: "READY_TO_UNPAIR",
rowIdentifier: store.getState().pageMode.rowIdentifier
}));
} else if (refresh === "pair") {
store.dispatch(changePageModeActionCreator({
mode: "READY_TO_PAIR",
rowIdentifier: topPartner,
rowIdentifierBottom: bottomPartner
}));
}
}
)
.then(
() => {
store.dispatch(removePairedVehicleActionCreator(topPartner)),
store.dispatch(removePairedVehicleActionCreator(bottomPartner))
}
)
}

Related

how to only return specific property form an array of objects in JavaScript

I only want to return the socket id, but forEach returns an undefined value, and find returns the entire object.
I only want the output to be 12345.
const users= [
{ host: true, socketId: "12345" },
{ host: false, socketId: "987654" },
{ host: false, socketId: "5678345" },
];
let socketId = users.forEach((user) => {
if (user.host === true) {
return user.socketId;
}
});//this return undefined
let socketId = users.find((user) => {
if (user.host === true) {
return user.socketId;
}
});//this return the whole object {host:true,socketId:"12345"}
const getHostSocketId = () => {
for (var i = 0; i < users.length; i++) {
if (users[i].host === true) {
return users[i].socketId;
}
}
};
let socketId = getHostSocketId(); //This works, but I'd rather use a method like the ones mentioned above.
console.log(socketId); //i want this to be 12345
let socketId = users.find(u => u.host)?.socketId
let answer = (inputArray) => {
const outputArray = []
inputArray.forEach((element) => {
if (element.host === true) {
outputArray.push(element.socketId)
}
})
return JSON.stringify(outputArray, null, ' ')
}

How to skip undefined/missing values in key-value pairs

I'm trying to build a citation generator from json in an API with data about images, stored in key-value pairs. I can get the data to return to the screen, but it always includes undefined in the citation. Sample manifest returns undefined as the creator since that isn't listed in this particular record. How can I keep any undefined value from being returned? I've tried changing the forEach to map, filtering at allMetadata by string length, using if !== undefined at insertCitation, and versions of those in different spots in the code.
EDIT: updated to provide full code, including print to page
(function () {
'use strict';
const buildCitation = {
buildMetadataObject: async function (collAlias, itemID) {
let response = await fetch('/iiif/info/' + collAlias + '/' + itemID + '/manifest.json');
let data = await response.json()
let allMetadata = data.metadata
let citationData = {};
allMetadata.forEach(function (kvpair) {
if (kvpair.value == undefined) {
return false;
} else if (kvpair.label === 'Title') {
citationData.itemTitle = kvpair.value;
} else if (kvpair.label === 'Creator') {
citationData.itemCreator = kvpair.value;
} else if (kvpair.label === 'Repository') {
citationData.itemRepository = kvpair.value;
} else if (kvpair.label === 'Collection Name') {
citationData.itemCollection = kvpair.value;
} else if (kvpair.label === 'Owning Institution') {
citationData.itemOwning = kvpair.value;
} else if (kvpair.label === 'Date') {
citationData.itemDate = kvpair.value;
} else if (kvpair.label === 'Storage Location') {
citationData.itemStorage = kvpair.value;
}
return true;
});
return citationData;
},
insertCitation: function (data) {
var testTitle = data.itemTitle;
console.log(testTitle);
const itemCite = `Citation: "${data.itemTitle}," ${data.itemDate}, ${data.itemCreator}, ${data.itemCollection}, ${data.itemOwning}, ${data.itemStorage}, ${data.itemRepository}.`;
const citationContainer = document.createElement('div');
citationContainer.id = 'citation';
citationContainer.innerHTML = itemCite;
// CHANGED to innerHTML instead of innerText because you may want to format it at some point as HTML code.
if (testTitle) {
document.querySelector('.ItemView-itemViewContainer').appendChild(citationContainer);
}
}
}
document.addEventListener('cdm-item-page:ready', async function (e) {
const citationData = await buildCitation.buildMetadataObject(e.detail.collectionId, e.detail.itemId);
console.log({ citationData });
buildCitation.insertCitation(citationData);
});
document.addEventListener('cdm-item-page:update', async function (e) {
document.getElementById('citation').remove();
const citationData = await buildCitation.buildMetadataObject(e.detail.collectionId, e.detail.itemId);
console.log({ citationData });
buildCitation.insertCitation(citationData);
});
})();
I've simplified your program. The undefined is coming from the fact that there is no item with label Date
const mappings = {
Date: 'itemDate',
Title: 'itemTitle',
Creator: 'itemCreator',
Repository: 'itemRepository',
'Storage Location': 'itemStorage',
'Owning Institution': 'itemOwning',
'Collection Name': 'itemCollection',
}
async function buildMetadataObject(collAlias, itemID) {
let response = await fetch('https://teva.contentdm.oclc.org/iiif/info/p15138coll25/1421/manifest.json');
let data = await response.json()
return data.metadata.reduce(
(acc, { label, value }) => ({ ...acc, [ mappings[label] ]: value }),
{}
)
}
function insertCitation(data) {
var testTitle = data.itemTitle;
const fieldBlackList = ['itemTitle'];
const itemCite = `Citation: "${data.itemTitle}," ${
Object.values(mappings).reduce((acc, cur) => {
if (fieldBlackList.includes(cur)) return acc;
const value = data[cur];
return value ? [...acc, value] : acc
}, []).join(', ')
}.`;
console.log(itemCite);
}
//MAIN PROGRAM
(async() => {
const citationData = await buildMetadataObject();
insertCitation(citationData);
})()

javascript recursive function memory leak

I am not good at English. Successfully make recursive call function. However, there is a memory leak for some reason. The question is that there is no return. The purpose of this feature is to view and explore objects, arrays, and the rest of their properties.
How do I change the code if I have a problem with my return?
Thank you in advance.
I was able to know the cause of the memory leak through Google dev tools profiles.
function recursionProperty(prop, obj, fn) {
if (Array.isArray(obj)) {
obj.forEach(item => recursionProperty('files', item, fn));
} else if (obj instanceof Object) {
Object.keys(obj).forEach(prop => {
const value = obj[prop];
recursionProperty(prop, value, fn);
});
} else {
fn(prop, obj);
}
}
recursionProperty(null, {foo:'bar', baz: ['x','y']}, (prop, obj) => console.log(prop, obj));
my original code
import _ from 'lodash';
import fs from 'fs';
import path from 'path';
import errors from '#feathersjs/errors';
import connections from '../../../connections';
import config from '../../../config';
/**
* #param req
* #param serviceItem
* #param query
* #returns {Promise<any>}
*/
const getServicePromise = async (req, serviceItem, query) => {
let serviceName = serviceItem;
if (typeof serviceItem !== 'string') {
serviceName = `datasets/${serviceItem.name}`;
}
return new Promise(async (resolve, reject) => {
let result;
let objResult;
try {
result = await req.app.service(serviceName).find(query);
} catch (e) {
result = null;
console.log(e);
}
// console.log(result);
if (result) {
if (typeof serviceItem !== 'string') {
objResult = { [serviceItem.name]: result.data };
} else {
objResult = { [serviceName]: result.data };
}
resolve(objResult);
} if (result === null) {
objResult = { [serviceName]: [] };
resolve(objResult);
} else {
reject({
error: 'Not found data.'
});
}
});
};
/**
* 파일 경로 프로퍼티를 찾는 재귀함수
* 객체, 배열, 원시타입 등 여러 타입이 섞여있어도 사용 가능
* #param prop
* #param obj
* #param fn
*/
function recursionProperty(prop, obj, fn) {
if (Array.isArray(obj)) {
obj.forEach(item => recursionProperty('files', item, fn));
} else if (obj instanceof Object) {
Object.keys(obj).forEach(prop => {
const value = obj[prop];
recursionProperty(prop, value, fn);
});
} else {
fn(prop, obj);
}
}
/**
* #param req
* #returns {Promise<{any}>}
*/
const getService = async req => {
const result = {};
const serverPath = [];
const { sheet, dataset, icon } = req.data;
const iconState = Object.prototype.hasOwnProperty.call(req.data, 'icon');
const sheetState = Object.prototype.hasOwnProperty.call(req.data, 'sheet');
const datasetState = Object.prototype.hasOwnProperty.call(req.data, 'dataset');
try {
// sheets
if (sheetState) {
const itemList = ['sheets'];
if (sheet.length === 0) {
const query = {
query: {
},
};
await Promise.all(itemList.map(serviceItem => getServicePromise(req, serviceItem, query))).then(data => {
data.forEach(item => {
Object.assign(result, item);
});
});
} else if (sheet.length > 0) {
const query = {
query: {
_id: {
$in: sheet,
},
},
};
await Promise.all(itemList.map(serviceItem => getServicePromise(req, serviceItem, query))).then(data => {
data.forEach(item => {
Object.assign(result, item);
});
});
} else {
result.sheets = [];
}
} else {
result.sheets = [];
}
// 파일 경로 구하기
if (sheet) {
const { sheets } = result;
// const filePath = [];
recursionProperty('files', sheets, (prop, value) => {
// 여기서 원하는 필드인지 검색후 처리함
if (prop === 'fullPath' && fs.existsSync(path.join(__dirname, '../../../../files', value))) {
// filePath.push(path.join(__dirname, '../../../../files', value));
serverPath.push(value);
}
});
// const deduplication = Array.from(new Set(serverPath));
// const deduplicationPath = await deduplicationFilePath(deduplication);
//
// Object.assign(result, { filePath: deduplicationPath });
} else {
// result.filePath = [];
}
// files
if (sheet) {
const deduplicationFiles = Array.from(new Set(serverPath));
if (deduplicationFiles.length > 0) {
const query = {
query: {
$sort: {
createdAt: -1,
},
fullPath: {
$in: deduplicationFiles,
},
}
};
const files = await req.app.service('files').find(query);
Object.assign(result, { files: files.data });
} else {
result.files = [];
}
} else {
result.files = [];
}
// dataset
if (datasetState) {
const query = {
query: {
// $limit: 100000
}
};
if (dataset.length === 0) {
const meta = await req.app.service('datasets/_meta_').find();
Object.assign(result, { _meta_: meta });
const db = await connections.getConnection(connections.DATASETS_DB);
const collectionNames = _.filter(await db.client.db(config.database_datasets.dbname).listCollections().toArray(), o => o.name !== '_meta_');
// collectionNames.forEach(str => {
// const detectA = iconvDetect.detect(Buffer.from(str.name));
// console.log('collection type', str.name, detectA);
// });
await Promise.all(meta.map(serviceItem => {
// const detectA = iconvDetect.detect(Buffer.from(serviceItem.key));
// console.log('meta type', serviceItem.key, detectA);
return getServicePromise(req, `datasets/${serviceItem.key}`, query);
})).then(data => {
Object.assign(result, { datasets: data });
});
} else if (dataset.length > 0) {
const metaQuery = {
query: {
$sort: {
createdAt: -1,
},
key: {
$in: dataset
}
}
};
const meta = await req.app.service('datasets/_meta_').find(metaQuery);
// console.log(meta);
Object.assign(result, { _meta_: meta });
await Promise.all(dataset.map(serviceItem => getServicePromise(req, `datasets/${serviceItem}`, query))).then(data => {
const d = Array.from(new Set(data));
const s = d.filter(item => item !== null);
if (d.length > 0) {
Object.assign(result, { datasets: s });
} else {
result.datasets = [];
result._meta_ = [];
}
});
} else {
result.datasets = [];
result._meta_ = [];
}
} else {
result.datasets = [];
result._meta_ = [];
}
if (iconState) {
const itemList = ['iconCategories', 'iconItems'];
const query = {};
if (icon.length === 0) {
await Promise.all(itemList.map(serviceItem => getServicePromise(req, serviceItem, query))).then(data => {
data.forEach(item => {
Object.assign(result, item);
});
});
}
} else {
result.iconCategories = [];
result.iconItems = [];
}
} catch (e) {
throw new errors.BadRequest('The data is invalid.', e);
}
return result;
};
export default getService;
There is most likely no memory leak in your code. Yes, recursive functions can be more memory aggressive than normal functions, because the call stack can grow very quickly, but remember that all functions will implicitly return even if there is no return statement. (Imagine that there is always a return undefined; line at the end of all your functions)
When doing a recursion, call stack will grow until you reach the bottom of a recursion branch (no function returns until then). Once the recursion branch end is reached, in your case this happens anytime you reach your else block, call stack will 'collapse' and all functions preceding will 'return'.
Memory will ultimately be freed by garbage collection as required.

Get output outside the ajax call

I'm using the libraby request for my ajax call, this library give me a response and after I'm using JSON.
I've got a constant id inside and where I'm block is to use this constant outside the request()
I know that I need a promises but I don't understand how to use it ...
const options = {
***
},
};
request(options, function(error, response, issue) {
const json = JSON.parse(issue);
for (let i = 0; i < json.versions.length; i++) {
const test = json.versions[i].name;
if (test === version) {
const id = json.versions[i].id; //here id
}
}
});
console.log(id); // I need to retrieve the const id here but id it's undefined, so how can I specified id
Try using:
const options = {
***
},
};
let id;
function getMyBody(options, callback) {
request(options, function(error, response, issue) {
const json = JSON.parse(issue);
for (let i = 0; i < json.versions.length; i++) {
const test = json.versions[i].name;
if (test === version) {
const id = json.versions[i].id; //here id
callback(id);
}
}
});
});
}
getMyBody(options,(id)=>{this.id = id; console.log(id);})
Use callback function
let id = 0;
fetchData = () => {
console.log(`id before ${id}`)
fetch('api', { method: 'GET',
headers: { 'Authorization': ** } })
.then((res) {
onCompleted(res)
}):;
}
onCompleted = (data) => {
id = data;
console.log(`id after ${id}`)
}
fetchData();
Simply create a variable outside the callback and assign it inside the callback result
var id
const options = {
***
},
};
request(options, function(error, response, issue) {
const json = JSON.parse(issue);
for (let i = 0; i < json.versions.length; i++) {
const test = json.versions[i].name;
if (test === version) {
id = json.versions[i].id; // here id is the id we declared in line 1.
}
}
});
console.log(id);
The value of id is going to be undefined at console.log(id); because the http request has not yet executed completely. You can either use callbacks, or a promise or a setInterval for id to be defined.
Using setInterval
var id
const options = {
***
},
};
request(options, function(error, response, issue) {
const json = JSON.parse(issue);
for (let i = 0; i < json.versions.length; i++) {
const test = json.versions[i].name;
if (test === version) {
id = json.versions[i].id; // here id is the id we declared in line 1.
}
}
});
var _interval = setInterval(() => {
if(id !== undefined) {
console.log(id);
// clearing interval
clearInterval(_interval)
}
}, 1000)
Using promise
below is an example of how to convert your request into a promise and then use the id
const options = {};
const promised_request = () => new Promise((resolve, reject) => {
request(options, function (error, response, issue) {
if (error) {
return reject(error);
}
const json = JSON.parse(issue);
for (let i = 0; i < json.versions.length; i++) {
const test = json.versions[i].name;
if (test === version) {
const id = json.versions[i].id;
return resolve(id);
}
}
});
});
promised_request().then((id) => {
// use your id here
console.log(id);
});

remove duplication in object array from firebase or filter it? look code for more info

Here I validate if my users status is true, and if they are, I put them in an array. The thing here is that next time it will validate, all those who already was true will be added to the same array. Can it be solved by filter instead of push, or should I take the validation in any other way?
import {
UPDATE_LIST_SUCCESS
} from './types'
var arr = []
export const fetchList = () => {
return (dispatch) => {
firebaseRef.database().ref().child('users')
.on('value', snapshot => {
snapshot.forEach(function (child) {
var data = child.val()
if (child.val().profile.status === true) {
arr.push(data)
}
})
dispatch({ type: UPDATE_LIST_SUCCESS, payload: arr })
})
}
}
You can do it like this:
import {
UPDATE_LIST_SUCCESS
} from './types'
export const fetchList = () => {
return (dispatch) => {
firebaseRef.database().ref().child('users')
.on('value', snapshot => {
var arr = snapshot.filter(function (child) {
return child.val().profile.status === true
}).map(function (child) {
return child.val();
});
dispatch({ type: UPDATE_LIST_SUCCESS, payload: arr })
})
}
}
So here is my not so pretty way of solving it, but it works.
import {firebaseRef} from '../firebase/firebase'
import {
UPDATE_LIST_SUCCESS
} from './types'
export const fetchList = () => {
return (dispatch) => {
const arrayToFilter = []
firebaseRef.database().ref().child('users')
.on('value', snapshot => {
let snap = snapshot.val()
// Get acces to the keys in the object i got from firebase
let keys = Object.keys(snap)
// iterate the keys and put them in an User object
for (var i = 0; i < keys.length; i++) {
let k = keys[i]
let name = snap[k].profile.name
let age = snap[k].profile.age
let status = snap[k].profile.status
let profile_picture = snap[k].profile.profile_picture
let users = {name: '', age: '', status: Boolean, profile_picture: ''}
users.name = name
users.age = age
users.status = status
users.profile_picture = profile_picture
// adding the user object to an array
arrayToFilter.push(users)
}
// filter and creates a new array with users depending if their status is true
let arr = arrayToFilter.filter(child => child.status === true)
dispatch({ type: UPDATE_LIST_SUCCESS, payload: arr })
})
}
}

Categories