Ive been using a azure mobile service back end to manipulated data before it is queried by an app. I have a feed that people can subscribe to an item and get the information from item. the link between the user and the items is in a new table that contains the userid and the itemid. i then do a for loop to find the each items matching itemid and then do an inner for loop to find all of the items details and take them and put them into a new array for sending.
It only seems to be working when i have the request respond after the inner loop like this. However i only get the item details for one of the subscribed items.
var itemfeedcollection = [];
var useritemconnections = tables.getTable('UserItemConnections');
useritemconnections.where({ username : user.userId }).read(
{
success: function(results)
{
if (results.length > 0)
{
for (var itemconnection = 0; itemconnection < results.length; itemconnection++)
{
var items = tables.getTable('Items');
items.where({ itemid : results[itemconnection].itemid }).read(
{
success: function(itemsresults)
{
if (itemsresults.length > 0)
{
for(var item = 0; item < itemsresults.length; item++)
{
itemfeedcollection.push(itemsresults[item])
}
request.respond(statusCodes.OK, itemfeedcollection);
}
else
{
request.respond(400, "We couldn't find any item details for the item you are subscribed to");
return;
}
}
});
}
}
else
{
request.respond(400, "You are not subscribed to any items");
return;
}
}
});
But if i move the request respond to after then outer loop where its suppose to be I get nothing at all. I would think i would at least get one item.
var itemfeedcollection = [];
var useritemconnections = tables.getTable('UserItemConnections');
useritemconnections.where({ username : user.userId }).read(
{
success: function(results)
{
if (results.length > 0)
{
for (var itemconnection = 0; itemconnection < results.length; itemconnection++)
{
var items = tables.getTable('Items');
items.where({ itemid : results[itemconnection].itemid }).read(
{
success: function(itemsresults)
{
if (itemsresults.length > 0)
{
for(var item = 0; item < itemsresults.length; item++)
{
itemfeedcollection.push(itemsresults[item])
}
}
else
{
request.respond(400, "We couldn't find any item details for the item you are subscribed to");
return;
}
}
});
}
request.respond(statusCodes.OK, itemfeedcollection);
}
else
{
request.respond(400, "You are not subscribed to any items");
return;
}
}
});
I am also curious if this is good practice to link items like this. I would also like to add that there maybe up to a few thousand itemconnections meaning that it would do a getTable for each of them. is that a bad thing?
It appears i was right and narrowed it down to the request respond being out side of the items results function. So i called both tables and then did my for loops in the results function then pushed each item to the array and now it is working correctly like this.
var itemfeedcollection = [];
var useritemconnections = tables.getTable('UserItemConnections');
useritemconnections.where({ username : user.userId }).read(
{
success: function(useritemconnectionsresults)
{
if (useritemconnectionsresults.length > 0)
{
var items = tables.getTable('Items');
items.read(
{
success: function(itemsresults)
{
if (itemsresults.length > 0)
{
for (var itemconnection = 0; itemconnection < useritemconnectionsresults.length; itemconnection++)
{
for (var item = 0; item < itemsresults.length; item++)
{
if (useritemconnectionsresults[itemconnection].itemid == itemsresults[item].itemid)
{
itemfeedcollection.push(itemsresults[item]);
}
}
}
request.respond(200, itemfeedcollection);
}
else
{
request.respond(400, "Where have all the items gone");
return;
}
}
});
}
else
{
request.respond(400, "You are not subscribed any items");
return;
}
}
});
This is good becuase now I dont have to call the items table thousands of times.
Related
I am trying to do a very simple stock counting app, and display dynamically the stocks for each item. When I try to pair the button with its item, it doesn't work, even though the 2 strings are actually a match.
Here is the faulty function:
socket.on('Stock init', (data) => {
items = data.items;
displayStock(items);
});
function displayStock(items) {
fridgeItem.forEach((fridgeItem) => {
for (let i = 0; i < items.length; i++) {
var databaseProduct = items[i].name;
var databaseQuantity = items[i].chilled.toString();
console.log(fridgeItem.textContent, databaseProduct);
}
if (fridgeItem.textContent === databaseProduct) {
fridgeItem.textContent = databaseProduct + ' ' + databaseQuantity;
} else {
console.log('err');
}
});
}
Answer might be stupid but I can't see it at the moment. Thanks
I have to go through an array of items and fetch the prices in the realtime database, but I want to show a loading message on start and after I finish loading I want to remove the loading message, but the way I did the message does not work its removed before the end of loading:
let loading = this.loadingCtrl.create({
content: 'Waiting...'
});
loading.present();
for (let i = 0; i <= this.Cart.length - 1; i++) {
let product = this.db.object('/menuItems/' + this.Cart[i].item.itemId);
product.valueChanges().subscribe((prodData: any) => {
if (prodData != null) {
this.Cart[i].item.price = prodData.price[0];
}
});
}
loading.dismiss();
How can I do this correctly?
You need to hide the loading indicator inside the subscriber. The simplest way is to hide it when the first data comes in:
for (let i = 0; i <= this.Cart.length - 1; i++) {
let product = this.db.object('/menuItems/' + this.Cart[i].item.itemId);
product.valueChanges().subscribe((prodData: any) => {
if (prodData != null) {
this.Cart[i].item.price = prodData.price[0];
}
loading.dismiss();
});
}
A bit more tricky is to hide it after all data comes back, but it doesn't have to be too hard. A simple way is to count how many responses you've gotten back. Once that is the same as the number of items in the cart, you can hide the loading indicator.
var responseCount = 0;
for (let i = 0; i <= this.Cart.length - 1; i++) {
let product = this.db.object('/menuItems/' + this.Cart[i].item.itemId);
product.valueChanges().subscribe((prodData: any) => {
if (prodData != null) {
this.Cart[i].item.price = prodData.price[0];
}
if (responseCount++ == this.Cart.length) loading.dismiss();
});
}
exports.equipp = function(user, User, msg) {
var itemname = msg.content.slice(8);
User.find({id: user.id}, function(err, usser) {
for(i = 0; i < usser[0].inventory.length; i++) {
if (usser[0].inventory[i].name == itemname) {
var Item = usser[0].inventory[i];
for (j = 0; j < usser[0].equipped.length; j++) {
if (Item.type == usser[0].equipped[j].type) {
}
if (j == usser[0].equipped.length -1) {
}
}
} else {
if (i == usser[0].inventory.length -1) {
msg.reply("You dont have that Item");
}
}
}
})
}
I'm having some porblems with it at the end at the if (j == usser[0].equipped.length -1) it never goes through and hence never adds an item to a empty inventory. I have items which atm only contain Name, Dmg, and Type im checking if the types match then if they do i add the item to the equipped array and remove it from the items array and vice versa for the item already equipped and when there is no item with that type in the array i need to just add it and remvoe it from the other array but my code fails at the point stated above an array of json objects {
"type": "Healm",
"armor": 4,
"name": "Starter Healm"
},
Instead of this :
for(i = 0; i < usser[0].inventory.length; i++) {
if (usser[0].inventory[i].name == itemname) {
var Item = usser[0].inventory[i];
// rest of code ...
} else {
if (i == usser[0].inventory.length -1) {
msg.reply("You dont have that Item");
}
}
}
Do:
for(i = 0; i < usser[0].inventory.length; i++) {
if (usser[0].inventory[i].name == itemname) {
var Item = usser[0].inventory[i];
// rest of code ...
}
}
if (!Item) {
msg.reply("You dont have that Item");
}
The determining factor whether you found the item is that you have defined Item. It after the loop you find that Item was not set, you know the item was not in the list. This obviously also works when the list is empty.
I have a table named "circle" and it represents mailing list.
Circle can contain user id in invitedUser or circle id in invitedCircle.
I need to get all circles id that contain specific user (in the code: 1-9).
For example if studantA is in CircleA
CircleA is in CircleB
so i need to get for studantA as output CircleA and CircleB.
I try to find all circles who conect each others by while and each, but the status of the job is : Could not connect to Cloud Code.
How can I run this query until no result found?
Parse.Cloud.job("fillMemberInCircles", function (request, status) {
var studentId = "123456789";
var output = [];
var lowLayer = [];
var highLayer = [];
// Get circles when the student appears in column invitedUsers
var invitedUsers = new Parse.Query("circles");
invitedUsers.equalTo("invitedUsers", studentId);
invitedUsers.find({
success: function (invitedUsersResults) {
if (invitedUsersResults.length > 0) {
for (var i = 0; i < invitedUsersResults.length; i++) {
output.push(invitedUsersResults[i].id);
lowLayer.push(invitedUsersResults[i].id);
}
var counter = lowLayer.length;
var _ = require('underscore.js');
while (counter > 0) {
//var _ = require('underscore.js');
_.each(lowLayer, function (currCircle) {
var invitedCirclesQuery = new Parse.Query("circles");
invitedCirclesQuery.equalTo("invitedCircles", currCircle);
invitedCirclesQuery.find().then(function (results) {
if (results.length != 0) { // item exists
for (var j = 0; j < results.length; j++) {
if (output.indexOf(results[j].id) == -1) {
output.push(results[j].id);
highLayer.push(results[j].id);
}
}
}
}).then(function () {
counter--;
if (counter == 0) {
if (highLayer.length == 0) {
console.log("OK");
lowLayer = [];
status.success("SUCSESS: " + output.length.toString());
} else {
lowLayer = highLayer;
counter = lowLayer.length;
highLayer = [];
}
}
});
});
}
}
//status.success("SUCSESS: " + output.length.toString());
},
error: function () {
status.error("[fillMemberInCircles] There was some error with queryMajors");
}
});
});
I’m doing a small YouTube app with node-webkit but I’m not a master with JavaScript.
I have some JSON objects from gdata responses and have items in a particular order, always the same. I can load everything in my playlist but I can’t keep the same order than the JSON object.
I dont understand sync/async calls.
Here's my code: http://pastebin.com/hM72T6rT
How can I do this with my for loop, so that I get all the items loaded in the same order as my JSON?
The functions are in the order I want:
function searchVideos(user_search){
try{
$('#items_container').empty();
youtube.feeds.videos({
q: ''+user_search+'',
'start-index' : ''+current_start_index+'',
'max-results': 25,
orderby: 'relevance'
},
function( err, data ) {
if( err instanceof Error ) {
console.log( err )
} else {
items=data.items
current_prev_start_index=current_start_index;
if (current_page == 1){
$('.back').css({'display':'None'});
} else {
$('.back').css({'display':'block'});
$('.next').css({'display':'block'});
}
if (items.length < 25) {
$('.next').css({'display':'None'});
}
for(var i=0; i<items.length; i++) {
video_loaded = false;
truc = function() { getVideoInfos('http://www.youtube.com/watch?v='+items[i].id) }(i);
}
}
});
}catch(err){
console.log('searchVideos err: '+err)
}
}
function getVideoInfos(video_link){
try {
ytdl.getInfo(video_link, function(err,info){
if(err) {
console.log(err);
} else {
printVideoInfos(info);
}
});
} catch(err) {
console.log('getVideoInfos err: '+ err);
}
}
function printVideoInfos(infos){
try{
var title = infos.title;
var thumb = infos.thumbnail_url;
var vid = infos.video_id;
$('#items_container').append('<div class="youtube_item"><img src="'+thumb+'" style="float:left;"/><p><b>'+title+'</b></p><div id="youtube_entry_res_'+vid+'"></div></div>');
//console.log(infos);
var num=infos.formats.length;
if ( parseInt(num) == 0) {
return;
}
var resolutions = new Array([]);
for(var i=0; i<num; i++) {
var vlink = infos.formats[i].url;
var resolution = infos.formats[i].resolution;
var resolution_full = infos.fmt_list[i][1];
var container = infos.formats[i].container;
// if resolution is alreay available in webm continue...
if ( $.inArray(resolution, resolutions) > -1 ) {
continue;
}
resolutions.push(resolution);
if (container == 'flv' || container == '3gp') {
continue;
}
var img='';
if (resolution == "720p" || resolution == "1080p") {
img='images/hd.png';
} else {
img='images/sd.png';
}
$('#youtube_entry_res_'+vid).append('<div class="resolutions_container"><a class="video_link" href="'+vlink+'" alt="'+resolution+'"><img src="'+img+'" class="resolution_img" /><span>'+ resolution+'</span></a><img src="images/down_arrow.png" /></div>');
}
if ($('#youtube_entry_res_'+vid+' div a.video_link').length == 0){
$('#youtube_entry_res_'+vid).parent().remove();
}
} catch(err){
console.log('printVideoInfos err: '+);
}
}
to keep them all in order, you are going to want to use the async module, Look up the async.series function, which should help you out. That will execute everything in the order you give it.