Meteor.call not working - javascript

I had this code working before I wanted to change the client side collection find/insert methods to server side. I removed insecure and autopublish from my meteor project, and changed my code to what it is below.
My angular Code in client/controllers/item-controller.js
angular.module('prototype').controller('ItemController', ['Config','$window','$meteor', function(Config, $window, $meteor) {
this.items = function(){
Meteor.call('getAllItems', function(err, res){
alert("error: " +err + " res: " + res );
return res;
});
}
My item-collection codee in server/item-collection-methods.js
Meteor.methods({
getAllItems : function(){
console.log("i got here")
return Items.find();
}
});
My main file in lib/app.js
Items = new Mongo.Collection("Items");
Before I had 15 items showing, now none of them show.
when I copy my Meteor.call function into the chrome console, all I get back is undefined.
I have a feeling it either has to do with the project structure, or the fact that autopublish and insecure are removed. Any advice would be helpful.
EDIT:
I did get something in my server console
I20150629-00:54:54.402(-4)? Internal exception while processing message { msg: '
method', method: 'getAllItems', params: [], id: '2' } Maximum call stack si
ze exceeded undefined

Meteor data transmission works with a publish/subscribe system. This system is able to replicate part of or all the data that is stored in your MongoDB (server) to the client in an in-memory DB (MiniMongo). Autopublish was publishing everything on the client, as you removed it there is nothing in your Items collection anymore.
In order to publish some data to the client you have to declare a publication on the server side:
Meteor.publish('allItems', function () {
//collection to publish
return Items.find({});
});
And subscribe on the client (either in the router or in a template):
Meteor.subscribe('allItems');
To learn more about this system you can read the official docs.
Concerning your method "getAllItems", you cannot directly send a cursor (Items.find()) on your data, that is why you are getting the error message "Maximum call stack size exceeded".
But you could send an array of these data by returning Items.find().fetch(). Also the call to a Meteor method is asynchronous, so you have to use the callback (more on Meteor methods)
Please note that by sending data over a method (which is perfectly acceptable) you lose the reactivity offered by the publish/subscribe system.

Related

PouchDB and React-Native not replicating .to() but .from() is working

For some reason documents created on my app are not showing up on my remote couchdb database.
I am using the following
import PouchDB from 'pouchdb-react-native'
let company_id = await AsyncStorage.getItem('company_id');
let device_db = new PouchDB(company_id, {auto_compaction: true});
let remote_db = new PouchDB('https://'+API_KEY+'#'+SERVER+'/'+company_id, {ajax: {timeout: 180000}});
device_db.replicate.to(remote_db).then((resp) => {
console.log(JSON.stringify(resp));
console.log("Device to Remote Server - Success");
return resp;
}, (error) => {
console.log("Device to Remote Server - Error");
return false;
});
I get a successful response the response:
{
"ok":true,
"start_time":"2018-05-17T15:19:05.179Z",
"docs_read":0,
"docs_written":0,
"doc_write_failures":0,
"errors":[
],
"last_seq":355,
"status":"complete",
"end_time":"2018-05-17T15:19:05.555Z"
}
When I go to my remote database, document_id's that am able to search and grab on the application do not show up.
Is there something I am not taking into account?
Is there anything I can do to check why this might be happening?
This worked when I used the same scripting method in Ionic and when I switched to React-Native I noticed this is the case.
NOTE: When I do .from() and get data from remote to the device, I get the data. For some reason it just isn't pushing data out
"Is there anything I can do to check why this might be happening?"
I would try switching on debugging as outlined here.
PouchDB.debug.enable('*');
This should allow you to view debug messages in your browser's JavaScript console.

Node.js flat-cache, when to clear caches

I have a Node.js server which queries MySQL database. It serves as an api end point where it returns JSON and also backend server for my Express application where it returns the retrieved list as an object to the view.
I am looking into implementing flat-cache for increasing the response time. Below is the code snippet.
const flatCache = require('flat-cache');
var cache = flatCache.load('productsCache');
//get all products for the given customer id
router.get('/all/:customer_id', flatCacheMiddleware, function(req, res){
var customerId = req.params.customer_id;
//implemented custom handler for querying
queryHandler.queryRecordsWithParam('select * from products where idCustomers = ? order by CreatedDateTime DESC', customerId, function(err, rows){
if(err) {
res.status(500).send(err.message);
return;
}
res.status(200).send(rows);
});
});
//caching middleware
function flatCacheMiddleware(req, res, next) {
var key = '__express__' + req.originalUrl || req.url;
var cacheContent = cache.getKey(key);
if(cacheContent){
res.send(cacheContent);
} else{
res.sendResponse = res.send;
res.send = (body) => {
cache.setKey(key,body);
cache.save();
res.sendResponse(body)
}
next();
}
}
I ran the node.js server locally and the caching has indeed greatly reduced the response time.
However there are two issues I am facing that I need your help with.
Before putting that flatCacheMiddleware middleware, I received the response in JSON, now when I test, it sends me an HTML. I am not too well versed with JS strict mode (planning to learn it soon), but I am sure the answer lies in the flatCacheMiddleware function.
So what do I modify in the flatCacheMiddleware function so it would send me JSON?
I manually added a new row to the products table for that customer and when I called the end point, it still showed me the old rows. So at what point do I clear the cache?
In a web app it would ideally be when the user logs out, but if I am using this as an api endpoint (or even on webapp there is no guarantee that the user will log out the traditional way), how do I determine if new records have been added and the cache needs to be cleared.
Appreciate the help. If there are any other node.js caching related suggestions you all can give, it would be truly helpful.
I found a solution to the issue by parsing the content to JSON format.
Change line:
res.send(cacheContent);
To:
res.send(JSON.parse(cacheContent));
I created cache 'brute force' invalidation method. Calling clear method will clear both cache file and data stored in memory. You have to call it after db change. You can also try delete specified key using cache.removeKey('key');.
function clear(req, res, next) {
try {
cache.destroy()
} catch (err) {
logger.error(`cache invalidation error ${JSON.stringify(err)}`);
res.status(500).json({
'message' : 'cache invalidation error',
'error' : JSON.stringify(err)
});
} finally {
res.status(200).json({'message' : 'cache invalidated'})
}
}
Notice, that calling the cache.save() function will remove other cached API function. Change it into cache.save(true) will 'prevent the removal of non visited keys' (like mentioned in comment in the flat-cache documentation.

Deleting data from MongoDB using MEAN stack

MEAN stack newbie here. I'm having difficulty understanding how delete works in MEAN. I'm using this SO Q&A and tutorial as guides, but whenever I test it out I get an error saying the data can't be deleted. Can somebody tell me what I've been doing wrong?
Here are my codes:
Controller JS
$scope.deleteProduct = function (value, idx) {
var this_id = value._id;
// delete
$http.delete('/api/products/delete:' + this_id)
.success(function (data) {
console.log(data);
})
.error(function (data) {
console.log('Error: ' + data);
})
}
Node Server
app.delete('/api/products/delete:', productController.delete);
Server's "Controller"
module.exports.delete = function (req, res) {
Service.remove({
_id: req.params._id
}, function (err, service) {
if (err) {
res.send(err);
}
else {
res.json({message: "Delete successful."});
}
});
}
This is how I understood this. Is this correct?
Controller JS gets the id to be deleted and calls $http's delete request(?), using said ID and the /api/products/delete:.
Node Server sees that I called '/api/products/delete:' and passes the request to Server's Controller to complete the request.
Server's Controller deletes the data and returns status.
Where did I go wrong? Please help.
Also, I've been seeing some posts that say $resource works better than $http. Why?
Thank you.
I think you've got a couple things wrong here.
In Express in order to use params you need to have something in the route that can be replaced. i.e /api/:id express replaces the :id with whatever you pass in so if you send /api/1, request.params.id is 1
So first problem is your route is
app.delete('/api/products/delete:', productController.delete);
tha dosen't mean anything to Express. I think you want
app.delete('/api/products/:id', productController.delete);
now req.params.id should contain the parameter you send. Note im dropping the underscore here. you could use
app.delete('/api/products/:_id', productController.delete); and keep the underscore if you like.
Second mistake I think is your Angular code. you have the : in your call it should just be
$http.delete('/api/products/' + this_id)
Now you're sending the route with whatever Id you are trying to delete i.e
/api/products/1
Now Express gets that and can map it to /api/products/:id and replace the id and now your controller should work. barring any other issues.
Edit
I'm not very familiar with Angular but I think the reason people are saying to use $resource is it is easier. You can directly call the different HTTP verbs directly on the objects themselves objects like
product.update and product.delete rather than trying to craft the http calls yourself. I'm sure there is a lot more to it than that but its a feature that's built into Angular that can be leveraged. I think one of the catches is the URLs for the resources just have to be set up a specific way on the server but I believe there was a way to override them in Angular.

Update a JSON file in AngularJS

I've got some data from a JSON file, which I use in my HTML getting it first from AngularJS like this:
$http.get('js/data.json').success(function(data) {
$scope.data = data;
});
And I want to update this JSON file after clicking a button in the HTML:
<button ng-click="postData(id)">Post</button>
You cannot write on files via JavaScript only (AngularJS).
You are to go via server side and point your "post" request to a server side script (i.e: PHP) and make that script do the job.
This sort of thing won't work. The file you are trying to write to would be on a server; and as it is right now, it would be a static resource. I'd suggest reading up on Angular resources, here. You can set up your server-side code to perform CRUD operations on the json file, but an actually database would be best. If you prefer to use a json format, Mongodb is your best choice; here is a link to Mongodb University, which offers free courses. I've done it in the past, and it's been great.
Now, for some actually help in your situation:
You can perform a GET request on your json file because it's seen as a static resource. The POST request, however, needs server-side scripting to do anything.
$http.get('api/YOUR_RESOURCE').success(function(data) {
$scope.database = data;
});
$http.post('api/YOUR_RESOURCE', {
data_key: data_value,
data_key2: data_value2
}).success(function(data) {
data[id].available = false;
});
This may be further ahead on your path to learning Angular, but here is a snippet of Node.js server code, with a Mongo database and Mongoose to handle the 'Schema', to help you get an idea of how this works:
var mongoose = require('mongoose'),
YOUR_RESOURCE = mongoose.model('YOUR_RESOURCE');
app.route('/api/YOUR_RESOURCE')
// This should be your GET request; 'api/
.get(
// Get all docs in resource
YOUR_RESOURCE.find().exec(function (err, data) {
if (err) {
return res.status(400).send({
message: SOME_ERROR_HANDLER
});
} else {
res.json(data); // return list of all docs found
}
});)
// Add new doc to database
.post(function (req, res) {
// The keys of the object sent from your Angular app should match
// those of the model
var your_resource = new YOUR_RESOURCE(req.body);
your_resource.save(function (err) {
if (err) {
return res.status(400).send({
message: SOME_ERROR_HANDLER
});
} else {
// returns newly created doc to Angular after successful save
res.json(your_resource);
}
});
);
Here is an SO page with a list of resources on getting started with Node; I recommend Node because of it's ease of use and the fact that it is written in JS. The Mongo University lessons also go through setting up you server for use with the database; you can choose between several flavors, such as Java, .NET, Python or Node.
There is a bit left out in the examples above, such as the Mongoose model and Node setup, but those will be covered in the resources I've linked to on the page, if you choose to read them. Hope this helps :)

Sails.js to client using sails.sockets.join and sails.sockets.broadcast doesn't return info to the client

I'm attempting to create a one to one chat using Sails.js and sails.io.js on the client side.
I can get the io.socket.get and io.socket.post to work, but I haven't been able to receive anything from either sails.sockets.broadcast or Model.publish as instructed here:
Personalized chat using Sails.js
or here
Sails.js + socket.io: Sending messages from server to clients
Server Side Code:
UserController.js
module.exports = {
listen: function(req, res) {
console.log("about to join " + userId);
sails.sockets.join(req.socket, req.param('userId'));
}
};
From: http://beta.sailsjs.org/#/documentation/reference/sails.sockets/sails.sockets.join.html
MessageController.js
// Some code to get userId and message model here
console.log("about to broadcast on " + userId);
sails.sockets.broadcast(userId, 'conversation_message', message);
// Did not JSONify the message model, not sure if I need to?
From: http://beta.sailsjs.org/#/documentation/reference/sails.sockets/sails.sockets.broadcast.html
Client Side Code:
// Some code to get userId...
io.socket.get('/user/listen', {
userId: userId
}, function() {
io.socket.on('conversation_message', function(message) {
console.log("we have a message");
});
});
When I hit the route that triggers the broadcast with userId, nothing is sent to this client code to log we have a message. Any ideas?
I have tried the Model.subscribe / Model.publish methods as well with no luck--same issue.
Update: The listen function doesn't actually return -- as someone suggested in a comment that they later deleted. Adding res.send(200); to the end of the listen function was enough to make it work.
If that person would add their comment again as an answer I'll accept it.
(That was me. I thought my comment might of been not worthwhile because i reread your post and you said you had the get working so I thought I was wrong. My comment was something to the effect below, but I don't remember verbatim)
Have you checked to make sure the you are actually getting a response on the client-side listen? What log statements are you actually getting throughout your code? Put a console.log('get user listen') or something inside of the Client-side socket.get.

Categories

Resources