API call in lazy-load function, limiting the api response - json

I've set up a project where Im limiting the API response to 5, and upon scrolling to the bottom o the page, I make a new API call to fetch the next 2 items in the API. But with the current code it only checks if the 5 items previously fetched exists in the cards state. Im quite unsure as to how to go about fetching the 2 next items in the API? Does anyone have any suggestions as to how to go about this? Thanks,
var app = new Vue({
el: '#app',
data: {
cards: []
},
methods: {
scroll(card) {
window.onscroll = () => {
let bottomOfWindow = document.documentElement.scrollTop +
window.innerHeight === document.documentElement.offsetHeight;
if(bottomOfWindow) {
const url =
'https://api.jsonbin.io/b/5cab36508b8d1301a25bd8fa/1/';
axios.get(url)
.then(response => {
for (var i = 0; i < this.cards.length; i++) {
console.log('Cards id: ', this.cards[i].id)
if(this.cards[i].id !==
response.data.results[i].id){
for (var x = 0; x < 2; x++) {
this.cards.push(response.data.results[x])
}
} else{
console.log('No more cards to load')
}
}
}
})
}
}
},
getAPI(){
const url = 'https://api.jsonbin.io/b/5cab36508b8d1301a25bd8fa/1/';
axios.get(url)
.then(response => {
for (var i = 0; i < 5; i++) {
this.cards.push(response.data.results[i]);
}
})
.catch(function (error) {
console.log(error);
})
.then(function () {
// always executed
});
console.log(this.cards)
}
},
mounted() {
this.scroll(this.card)
}
})

Changed the method in which you do the checking. Instead of doing it from cards length you loop through the results length and once you reach a card that doesnt exist you add them, keep track of the amount added and return after 2 or when there is none left. I changed the loop logic to so.
//Card with position i from results doesn't exist
if(this.cards[i] == undefined){
//add this card - maybe add more logic to check for duplicate incase of reordering of response
this.cards.push(response.data.results[i])
//track card added
cardsAdded++;
} else {
console.log('No more cards to load')
}
//check if cards added has reach limit of 2
if(cardsAdded == 2)
return;
See: https://jsfiddle.net/as4dm03q/

Related

Trying to use comgooglemaps with waypoints internet url

I want to send coordinates to a user's google maps with waypoints. Unfortunately, it is only sending the starting point and destination. I need it to work for all devices regardless of their last update, if possible. The goal is for the user to be able to add up to 4 waypoints or none at all and the code to work normally. I also looked into node modules, but was unable to find any that met my needs. I am open to all suggestions.
`const rideWithGoogle = () => {
console.log("currentDestinationCords: ", currentDestinationCords)
console.log("currentLocation: ", currentLocation)
console.log("Ride with Google: ", waypointString)
if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
// Open Google Maps with coordinates on iOS
//window.location.href = `comgooglemaps://?daddr=${encodedPolyline}`;
//window.location.href = `comgooglemaps://?q=${currentLocation?.lat}%2C${currentLocation?.lng}&waypoints=${waypointString}&daddr=${currentDestinationCords[0]}%2C${currentDestinationCords[1]}`;
window.location.href = `comgooglemaps://?saddr=${currentLocation?.lat}%2C${currentLocation?.lng}&daddr=${currentDestinationCords[0]}%2C${currentDestinationCords[1]}&waypoints=via:${waypointString}`
//window.location.href = `comgooglemapsurl://www.google.com/maps/dir/${currentLocation?.lat},${currentLocation?.lng}/${waypointString}/${currentDestinationCords[0]},${currentDestinationCords[1]}`
} else {
if (navigator.getInstalledRelatedApps) {
navigator.getInstalledRelatedApps().then(relatedApps => {
if (relatedApps.some(app => app.platform === "play" && app.id === "com.google.android.apps.maps")) {
// Google Maps is installed, so launch it with the coordinates
navigator.launchApp("com.google.android.apps.maps", `geo:0,0?q=${currentLocation?.lat}%2C${currentLocation?.lng}&waypoints=${waypointString}&daddr=${currentDestinationCords[0]}%2C${currentDestinationCords[1]}`).then(() => {
console.log("Google Maps launched successfully!");
}).catch(err => {
console.log("Error launching Google Maps: ", err);
});
} else {
console.log("Google Maps is not installed on this device.");
}
});
}
}
}
const go = () => {
console.log("waypoint: ", waypoint)
if (waypoint?.length < 1) {
{!riderDidPay && setPaymentOption(true)};
if (riderDidPay) {
if (waypoint.length > 0) {
let wps = "";
for (let i = 0; i < waypoint.length; i++) {
wps += `${waypoint[i]?.lat}%2C${waypoint[i]?.lng}|`;
}
setWaypointString(wps.slice(0, -1));
}
}
} else {
// setIsUserDriving(!isUserDriving);
// map?.panTo(currentLocation);
// map?.setZoom(20);
if (waypoint?.length > 0) {
let wps = "";
for (let i = 0; i < waypoint.length; i++) {
wps += `${waypoint[i]?.lat}%2C${waypoint[i]?.lng}|`;
}
setWaypointString(wps.slice(0, -1));
setReadyToDrive(true);
}
setReadyToDrive(true);
}
}`

Autodesk-XLSExtension, undefined viewer

Im trying to implement the XLS Extension. In the ModelData class, i cannot get objects leaf nodes because the viewer is undefined.
Here is the problematic method:
getAllLeafComponents(callback) {
// from https://learnforge.autodesk.io/#/viewer/extensions/panel?id=enumerate-leaf-nodes
viewer.getObjectTree(function (tree) {
let leaves = [];
tree.enumNodeChildren(tree.getRootId(), function (dbId) {
if (tree.getChildCount(dbId) === 0) {
leaves.push(dbId);
}
}, true);
callback(leaves);
});
}
Im getting Cannot read properties of undefined (reading 'getObjectTree') , meaning viewer is undefined.
However, viewer is working and displaying documents.
I tried to call it by window.viewer and this.viewer to no avail.
Thanks in advance for any help
It looks like it missed two lines. Could you try the revised one below?
// Model data in format for charts
class ModelData {
constructor(viewer) {
this._modelData = {};
this._viewer = viewer;
}
init(callback) {
var _this = this;
var viewer = _this._viewer;
_this.getAllLeafComponents(function (dbIds) {
var count = dbIds.length;
dbIds.forEach(function (dbId) {
viewer.getProperties(dbId, function (props) {
props.properties.forEach(function (prop) {
if (!isNaN(prop.displayValue)) return; // let's not categorize properties that store numbers
// some adjustments for revit:
prop.displayValue = prop.displayValue.replace('Revit ', ''); // remove this Revit prefix
if (prop.displayValue.indexOf('<') == 0) return; // skip categories that start with <
// ok, now let's organize the data into this hash table
if (_this._modelData[prop.displayName] == null) _this._modelData[prop.displayName] = {};
if (_this._modelData[prop.displayName][prop.displayValue] == null) _this._modelData[prop.displayName][prop.displayValue] = [];
_this._modelData[prop.displayName][prop.displayValue].push(dbId);
})
if ((--count) == 0) callback();
});
})
})
}
getAllLeafComponents(callback) {
var _this = this;
var viewer = _this._viewer;
// from https://learnforge.autodesk.io/#/viewer/extensions/panel?id=enumerate-leaf-nodes
viewer.getObjectTree(function (tree) {
var leaves = [];
tree.enumNodeChildren(tree.getRootId(), function (dbId) {
if (tree.getChildCount(dbId) === 0) {
leaves.push(dbId);
}
}, true);
callback(leaves);
});
}
hasProperty(propertyName){
return (this._modelData[propertyName] !== undefined);
}
getLabels(propertyName) {
return Object.keys(this._modelData[propertyName]);
}
getCountInstances(propertyName) {
return Object.keys(this._modelData[propertyName]).map(key => this._modelData[propertyName][key].length);
}
getIds(propertyName, propertyValue) {
return this._modelData[propertyName][propertyValue];
}
}

How to determine completion?

I am creating currency rates website backend in node js with MongoDB and MySQL,
At first I am storing data into MongoDB from API and afterwards, for saving RAM and CPU I have decided to create and store analytical data into MySQL.
Please look at following code,
update24HRateArr: () => {
var da = [];
db.query('TRUNCATE TABLE `rate24h`', (xerr, xres) => {
if (xerr) console.log(xerr.message);
});
mdb.currency((currList) => {
if (currList && currList.length > 0) {
currList.length = 50;
for (var c = 0; c < currList.length; c++) {
mdb.rateArr(currList[c], '24h', (data) => {
if (data && data.length > 0) {
for (var i = 0; i < data.length; i++) {
var tmp = [];
tmp.push(data[i].id);//1->id
tmp.push(i);//2->number
tmp.push(data[i].time);//3->time value
tmp.push(data[i].price_usd);//4->price usd
tmp.push(data[i].price_btc);//5->price btc
tmp.push(data[i].price_inr);//6->price inr
tmp.push(fn.time.unix());//7->DB update time
da.push(tmp);
}
//main area for done call
/*
if (da.length == 1200) {
db.query('INSERT INTO `rate24h` VALUES ?', [da], (err, datax) => {
if (err) console.log(err);
else {
console.log(`${fn.time.timeStamp()} Data(${datax.affectedRows}) Inserted for Rate24H`);
}
});
console.log(da);
}*/
console.log(`inside i ${da.length}`);
}
console.log(`inside iRateArr ${da.length}`);
});
//console.log(`inside c ${da.length}`); <- always 0 no way
}
}
else {
console.log('Currency Loading failed');
}
});
},
Now, I know that length of da var is gonna be 1200 in this case because 50 currencies and 24 hours but in some cases it's flexible,
I can't exactly determine when this da var updating will be completed via for loops so I can execute insert query to mysql
that if(da.length ===1200) is not enough I need exact point that I can execute INSERT query.
Thank you

variable value becomes undefined in NodeJS ExpressJS

I am working with NodeJS using ExpressJS framework in a mysql backend. I am running a query inside a for loop and my loop and work afterwards depends on the return value of the query. I am not very good with mysql query so I am running it through a for loop.
The problem is, due asynchronous [I guess!], the for loop ends long before the query result comes out.
Here is my code:
function search_people_step2(user_id, search_criteria, user_friend)
{
var first_name_friends = [];
var last_name_friends = [];
for(var i = 0; i < user_friend.length; i++)
{
con.query("SELECT first_name, second_name FROM user WHERE userid = ?", user_friend[i],function(err, rows)
{
if(err)
{
//error;
}
else
{
if(rows.length == 0)
{
//nothing gets returned
}
else {
console.log(rows);
first_name_friends[i] = rows[0].first_name;
last_name_friends[i] = rows[0].second_name;
}
}
});
}
Now,I can get the value (using console.log) inside the query statement, however, on the outside, the value becomes empty (undefined) since the rest of the code has already been computed.
How can I solve this?
Thanks in advance.
The first thing that I find weird in your code is that you are not using an IN statement in your SQL query (not directly related to your problem though) which means you are making as many requests as there are entries in user_friend. The problem is that the SQL library is implemented asynchronously and you cannot avoid it. BUT you can handle it elegantly with Promises which are ES6 features:
(I didn't test the code but I think it should work)
function search_people_step2(user_id, search_criteria, user_friend)
{
return new Promise((resolve,reject)=>{
var first_name_friends = [];
var last_name_friends = [];
var placeHolders=user_friend.map(()=>"?").join(",");
con.query("SELECT first_name, second_name FROM user WHERE userid IN ("+placeHolders+")",user_friend,(err,rows)=>{
if(err)
reject(err);
else{
rows.forEach(row=>{
first_name_friends.push(row.first_name);
last_name_friends.push(row.second_name);
});
resolve({first_name_friends,last_name_friends});
}
});
});
}
And call your function like this :
search_people_step2(id,crit,friends).then(result=>{
//handle result asynchronously as there is no choice
console.log(result.first_name_friends);
console.log(result.last_name_friends);
}).catch(err=>{
//handle error
});
You are right, your problem is the asynchronous nature of the mysql call. You have to provide a callback to your search_people_step2 function.
You may change it like this:
search_people_step2(user_id, search_criteria, user_friend, callback)
In your function body you may use a library called async to handle all the callbacks properly. Here is an example for the usage:
async.eachSeries(user_friend, function(item, eachCb){
con.query("SELECT first_name, second_name FROM user WHERE userid = ?",
user_friend[i],function(err, rows) {
if(err) {
eachCb('error');
}
else {
if(rows.length == 0){
//nothing gets returned
eachCb(null);
}
else {
console.log(rows);
first_name_friends.push(rows[0].first_name);
last_name_friends.push(rows[0].second_name);
eachCb(null);
}
}
}, callback);
});
This calls each query in order on every item of the array and calls the inner callback if finished. When all items are processed or an error occured the outer callback is called. See the async library for further documentation.
simplest solution is
function search_people_step2(user_id, search_criteria, user_friend)
{
var first_name_friends = [];
var last_name_friends = [];
for(var i = 0; i < user_friend.length; i++)
{
con.query("SELECT first_name, second_name FROM user WHERE userid = ?", user_friend[i],function(err, rows)
{
if(err)
{
//error;
}
else
{
if(rows.length == 0)
{
//nothing gets returned
}
else {
console.log(rows);
first_name_friends[i] = rows[0].first_name;
last_name_friends[i] = rows[0].second_name;
}
if(i==user_friend.length-1){
//do your work here which you want to perform in end
}
}
});
}
or use async library
var async = require('async');
var first_name_friends = [];
var last_name_friends = [];
async.series([function(cb){
function search_people_step2(user_id, search_criteria, user_friend)
{
for(var i = 0; i < user_friend.length; i++)
{
con.query("SELECT first_name, second_name FROM user WHERE userid = ?", user_friend[i],function(err, rows)
{
if(err)
{
//error;
}
else
{
if(rows.length == 0)
{
//nothing gets returned
}
else {
console.log(rows);
first_name_friends[i] = rows[0].first_name;
last_name_friends[i] = rows[0].second_name;
}
if(i==user_friend.length-1){
cb()
}
}
});
}
},function(cb){
//do your work here
}],function(err){})

How to pass a whole dojox.grid.DataGrid store(items json data) to servlet?

I have a button on page - when clicked, it passes all the data to the servlet that could update each row data. My question is how to pass the whole store to the servlet as json data? Is there any easy way? Thanks
Here is some code I wrote to get the store to an object. Then it can be converted to JSON using dojo.toJson(obj);. I learned about this from the dojotoolkit website originally. (Give credit where credit is due). I realize this code is huge and nasty. When I looked for a better way about a year back I could not find one.
JsonHelper.storeToObject = function(store) {
var object = [];
var index = -1;
store.fetch({
onItem : function(item, request) {
object[++index] = JsonHelper.itemToObject(store, item);
}
});
return object;
};
JsonHelper.itemToObject = function(store, item) {
// store:
// The datastore the item came from.
// item:
// The item in question.
var obj = {};
if (item && store) {
// Determine the attributes we need to process.
var attributes = store.getAttributes(item);
if (attributes && attributes.length > 0) {
var i;
for (i = 0; i < attributes.length; i++) {
var values = store.getValues(item, attributes[i]);
if (values) {
// Handle multivalued and single-valued attributes.
if (values.length > 1) {
var j;
obj[attributes[i]] = [];
for (j = 0; j < values.length; j++) {
var value = values[j];
// Check that the value isn't another item. If
// it is, process it as an item.
if (store.isItem(value)) {
obj[attributes[i]].push(itemToObject(store,
value));
} else {
obj[attributes[i]].push(value);
}
}
} else {
if (store.isItem(values[0])) {
obj[attributes[i]] = itemToObject(store,
values[0]);
} else {
obj[attributes[i]] = values[0];
}
}
}
}
}
}
return obj;
};