I am trying to use JS to query DynamoDB and parse the returned data. I must admit that I am new to JavaScript but I am having some weird behaviours.
In the following function I am passing an array of dates and I am retrieving objects from my table
var queryDynamo = function(dateArray){
console.log(dateArray)
for (var i = 0; i < dateArray.length; i++) {
var params = {
TableName : "myTable",
KeyConditionExpression: "#day = :st ",
ExpressionAttributeNames:{
"#day": "day"
},
ExpressionAttributeValues: {
':st': dateArray[i]
}
};
var resp = docClient.query(params, function(err, data) {
if (err) {
console.log("ERR:"+JSON.stringify(err, undefined, 2))
} else {
data.Items.forEach(function(element) {
console.log(element)
});
}
});
}
console.log(resp.response)
return;
}
--> The following is the output
constructor {request: constructor, data: null, error: null, retryCount: 0, redirectCount: 0, …}
data:
Count: 4
Items: (4) [{…}, {…}, {…}, {…}]
ScannedCount: 4
__proto__: Object
error: null
httpResponse: constructor {statusCode: 200, headers: {…}, body: Uint8Array(1134), streaming: false, stream: i, …}
maxRedirects: 10
maxRetries: 10
nextPage: ƒ (e)
redirectCount: 0
request: constructor {domain: undefined, service: t.c…r.t.constructor, operation: "query", params: {…}, httpRequest: constructor, …}
retryCount: 0
__proto__: Object
The query succeeds but the result is kind of weird.
resp.response correctly contains the data object but I cannot access it. It says that it's null while it clearly is not since it has 4 Items.
Any thoughts?
You are attempting to print the response data before it exists. Your console.log(resp.response) line is executing before the DynamoDB query has completed and its results have been unmarshalled. This is a common gotcha in asynchronous JavaScript.
One way to see the response data in the AWS.Request object is to wait for it, like this (though you would never typically do this in JavaScript):
var req = docClient.query(params, function(err, data) {
// as before: handle err, data
)};
setTimeout(function () {
console.log('Response data:', JSON.stringify(req.response.data));
}, 2000);
A more common pattern is to use the promise variants of the SDK methods, like this:
docClient.query(params).promise()
.then(data => doSomething(data))
.catch(err => logError(err));
Related
I'm using autoCompletejs and want to fetch my list of keys from my backend, but am getting the following error:
autoComplete.js:119 Uncaught (in promise) TypeError: Invalid attempt to iterate non-iterable instance. In order to be iterable, non-array objects must have a Symbol.iterator method.
My "data" code:
data: {
src: async () => {
try {
// Loading placeholder text
document.getElementById("autoComplete").setAttribute("placeholder", "Loading...");
// Fetch External Data Source
const source = await fetch("/suppliers");
const data = await source.json();
console.log(data)
// Post Loading placeholder text
document.getElementById("autoComplete").setAttribute("placeholder", autoCompleteJS.placeHolder);
// Returns Fetched data
return data;
} catch (error) {
return error;
}
},
keys: fetch("/keys").then(response => response.json()) //.then(jsonData => console.log(jsonData)
),
cache:true
},
Values logged:
jsonData:
(10) ['263897', '186000', '146294', '278717', '189906', '246548', '130111', '157960', '947854', '138753']
0: "263897"
1: "186000"
2: "146294"
3: "278717"
4: "189906"
5: "246548"
6: "130111"
7: "157960"
8: "947854"
9: "138753"
length: 10
[[Prototype]]: Array(0)
data:
0: {100058: 'Supplier1', 100211: 'Supplier2', 100476: 'Supplier3', 100986: 'Supplier4' …}
length: 1
[[Prototype]]: Array(0)
Looks like your /suppliers endpoint returns a singleton array (an array with only one item in it) with an object of id / label pairs.
First, singleton arrays are useless. I'd change the backend to return an array of objects but in the meantime, you could map the result to something more useful
data: {
src: async (query) => {
const res = await fetch("/suppliers");
if (!res.ok) {
throw new Error(`${res.status}: ${await res.text()}`);
}
// get the first / only array item
const [data] = await res.json();
// map to an array of objects with id & label properties
return Object.entries(data).map(([ id, label ]) => ({ id, label }));
},
keys: ["label"],
}
I am not into javascript and angular, currently working on some UI task and has workable/little knowledge of javascript
what i want, base on a key field filter out the objects.
currently what code is doing, hitting a api, which is storing some result in an array. this array result are in object (promise object) i guess, and i need to set out a filter condition on this object base on some value.
but for me issue is, object does not have key same as response, it store. data like this
Array(5) [ {…}, {…}, {…}, {…}, {…} ]
0: Object { _isScalar: false, source: {…}, operator: {…} }
1: Object { _isScalar: false, source: {…}, operator: {…} }
2: Object { _isScalar: false, source: {…}, operator: {…} }
3: Object { _isScalar: false, source: {…}, operator: {…} }
4: Object { _isScalar: false, source: {…}, operator: {…} }
length: 5
so even if i iterate through each object i cant find the key which is my filter criteria.
below is code related to this
getSomeThing(
name: string,
dcId: any
): Promise<any[]> {
const url = `<url>`;
return this.http.get(url, { headers: this.sharedService.getHeaders() })
.toPromise()
.then(response => this.getSomeThingOneByOne(name, dcId, response.json()))
.catch(error => this.sharedService.handleError(error));
}
private getSomeThingOneByOne(name, dcId, someIds): Promise<any> {
const someObservables = [];
someIds.forEach(some => someObservables.push(this.getsomethingObservable(name, dcid, some)));
return Observable.forkJoin(someObservables)
.toPromise()
.catch(error => this.sharedService.handleError(error));
}
getsomethingObservable(
name: string,
dcId: any,
someId: any
): Observable<any> {
const url = `<url>`;
return this.http.get(url, { headers: this.sharedService.getHeaders() })
.map((response: Response) => {
const vm = response.json();
return vm;
})
.catch((error: any) => Observable.throw(this.sharedService.handleError(error)));
}
note i have change the name of function and variable.,
now here, getsomeThing call an api which return a list of ids and pass it to getSomethingOneByOne as array ie [1,2,3,4,5] , and this function getSomethingOneByOne call getsomethingObservable to get the data related to that id.
what i want is once i recied the data i should check a certain value in it or in getsomethingObservable check the value it self for that key and filter out the result.
but due since i am not able to read the data in array someObservables in function getSomeThingOneByOne raw i cant add filter condition there.
need help here as it requires knowledge of promise, obserable, angular and typescript which i lack.
just solved this by taking reference from #sonusindhu suggestion and taking reference from here too.
i had made changes on getSomeThingOneByOne as below and it worked
private getSomeThingOneByOne(name, dcId, someIds): Promise<any> {
const someObservables = [];
someIds.forEach(some => someObservables.push(this.getsomethingObservable(name, dcid, some)));
return Observable.forkJoin(someObservables)
.toPromise()
.then(response => {
var data = response.filter(val=>val[<somekey>]!='<a certain value>');
return data;
})
.catch(error => this.sharedService.handleError(error));
}
This is my res.data.enquiry - object I'm getting from api call
{
active: true
createdAt: "2021-09-03T05:58:32.584Z"
ID: {category: Array(1),
Images: Array(5),
_id:'6131b96650a4b8127f7c59c8',
loginMethod: 0,
phone: '65565656', …}
messages: (4) [{…}, {…}, {…}, {…}]
__v: 3
_id: "COOK000000000036"
}
My UseState where I initialized the SingleEnq as an empty object to set it with res.data.enquiry during the fetch from api. (also tried null)
const [singleEnq, setSingleEnq] = useState({});
My fetch function
function getOneticket(userID) {
axios
.get(`admin/enquiry/get/one?enquiryID=${userID}`)
.then((res) => {
setSingleEnq(res.data.enquiry)
})
.catch((err) => {
console.log(err, "error message for get one ");
});
}
My useState remains empty. Dont know the reason. It's not setting up the data from the api.
product.map is not a function, i've tried almost all the fix from the web still not working. also, i've tried to console.log(response.data) and it response success
react ver 7.0
constructor () {
super()
this.state = {
products: []
};
}
componentDidMount(){
axios.get('http://localhost:8000/api/v1/products/1')
.then(response => {
this.setState({ products: response.data });
})
.catch(function (error) {
console.log(error);
})
}
render(){
var { products } = this.state;
var merk = products.map(products => {products.merk} );
got error products.map is not a function at var merk=.....
thanks.
console.log:
{success: true, data: Array(1), message: "Phone retrieved Successfully.."}
data: Array(1)
0: {id_product: 1, merk: "Xiaomi ", tipe: "Mi Note 10", soc_nama: "Qualcomm", soc_tipe: "Snapdragon 855+", …}
length: 1
__proto__: Array(0)
message: "Phone retrieved Successfully.."
success: true
__proto__: Object
products.map is not a function, this mean products is not an array
In your API at componentDidMount, You have to access to the data that you return from server. You accessing to response.data, this mean you just access to the data of XMLHttpRequest, not data of your API.
Try to console.log(response.data), and see which one is the array data that you want to get from server
I do a http call to get an Array with objs. And now I want to call for each objs that return me an ID another http call. After all I want to have one observable result.
So far I managed to get for each index a http call. The problem instead of one result I got multiple.
getStats(tag: string) {
return this.service.getClanByClanTag(tag)
.map(clan => {
return clan.memberList; //the arr that return the ID's
})
.switchMap((member: PlayerByMemberListType[]) => {
return member; // singleObj of the arr
})
.concatMap((singleMember) => {
return this.service.getPlayerData(singleMember.tag).map(player => {
//push data to the new arr which should return only one time
this.newArr.push({
tag: singleMember.tag,
name: singleMember.name,
warStars: player.warStars,
trophiesNightBase: singleMember.versusTrophies
});
return this.newArr;
});
});
}
This is what the console prints out after subscribing to it:
Array [ {…} ]
Array [ {…}, {…} ]
Array(3) [ {…}, {…}, {…} ]
Array(4) [ {…}, {…}, {…}, {…} ]
Array(5) [ {…}, {…}, {…}, {…}, {…} ]
...
I know I need some kind of Observable.forkJoin but I don't know how integrate it in the code.
Try something like this:
this.service.getClanByClanTag(tag)
.mergeMap(clan => clan.memberList)
.mergeMap(
member => this.service.getPlayerData(member.tag), // supposedly this returns an observable
(member, player) => ({
tag: member.tag,
name: member.name,
warStars: player.warStars,
trophiesNightBase: member.versusTrophies
})
)
.toArray()
So basically what you want to achieve is this.
Get the clan info
Using clan info from step 1, get the memberList in the clan
For each member inside the memberList, get the players
You will need to think of a way to preserve the info at step2 when before switchMap in step3. Usually we will use a Subject, but in the case if you do not want to, simply map the Observable to preserve the data:
getStats(tag: string) {
return this.service.getClanByClanTag(tag)
.map(clan => {
return clan.memberList; //the arr that return the ID's
})
.switchMap((memberList: PlayerByMemberListType[]) => {
//note that the following map is a function of javascript array, not Observable
//it returns an array
let arrayOfObservables = memberList.map(singleMember => {
this.service.getPlayerData(singleMember.tag)
//map the data so as to preserve the data of singleMember
//by creating a new object, using Object.assign
.map(playerData => {
return Object.assign({memberData: singleMember}, playerData,)
});
})
return Observable.forkJoin(arrayOfObservables);
})
.map(players => {
//players is an array of Object that is the format of {memberData:singleMember, playerData:player)
//perform Object destructuring method
return players.map(({memberData,playerData}) => {
return {
tag: memberData.tag,
name: memberData.name,
warStars: playerData.warStars,
trophiesNightBase: memberData.versusTrophies
}
})
})
}