Session is not defined within Meteor.methods on server side but is on client side [duplicate] - meteor

This question already has answers here:
Meteor Session is not defined
(4 answers)
Closed 7 years ago.
I have a method that sets the session variable:
Meteor.methods({
updateSomething: (k) => {
CollectionOfSomething.insert({
k: k
});
Session.set('latestSomething', CollectionOfSomething.findOne({
k: k
});
}
});
What happens next is something contradictory to me. Since the methods are defined within lib folder (which is a correct way to do), a call invokes the method both on client and on the server. On the client, it yields new value for the session variable latestSomething, and it refreshes every time. But on the server, I'm getting an exception:
Exception while invoking method 'updateSomething' ReferenceError: Session is not defined
This exception is just a warning and doesn't kill the app instance. But it seems not a good practice, and all those messages stuff the server logs without any value.
What should I do then? What's the Meteor idiomatic way to do?

You can't use session on the server. It's meant for reactivity on the client. Set it on the callback like so:
Meteor.call('updateSomething', yourThing, function (err, id) {
if (!err) {
Session.set('somevar', id);
}
})
where your meteor method looks like this
Meteor.methods({
updateSomething: function (thing) {
return MyCollection.insert(thing); // returns the id
}
});

The Session object is only available on the client (see http://docs.meteor.com/#/basic/session - both of the function definition boxes say "Client"). Your best option is to return the result of your CollectionOfSomething.findOne() fetch and then use Session.set in the client's callback function.
The Session is an ephemeral object that is lost on a hard page refresh or when the user manually navigates to a different page, so maintaining it on the server wouldn't make any sense.

Related

Meteor.call is very slow when responding back

I am facing performance problem with Meteor.call(). I have a method on server side which gets execute within a millisecond but when I seek a response in the client side, it is taking long to get the response data inside the callback function. Is anyone experience the problem before?
I was using Meteor 1.12.1 and updated to Meteor 2.1.1 hoping to solve the problem by updating but I didn't find any difference.
Update: I am facing issue on all environment (osx, linux, windows).
For eg: This is my server code
Meteor.methods({
newEntry() {
//This method is executed within millisecond
}
})
This is my client code
function submitEntry(data) {
Meteor.call(
'newEntry',
data,
(error, res) => {
//Here I am getting the response after long wait.
},
);
}
Can somebody help me on this?
I found the solution. As per the Meteor docs.
Once the Method has finished running on the server, it sends a result message to the client with the Method ID generated in step 2, and the return value itself. The client stores this for later use, but doesn’t call the Method callback yet. If you pass the onResultReceived option to Meteor.apply, that callback is fired.
Ref: https://guide.meteor.com/methods.html#advanced-boilerplate
So if you want your call back to be triggered once the server method return the value then you can use Metor.apply method with the option onResultReceived.
Meteor.apply(
"methodName",
[...params],
{
onResultReceived: function() {
// Whatever you want to do after callback.
}
}

MeteorJs "loginWIthPassword" seems not to work in method

It seems that the "Meteor.loginWithPassword" function does not work when called in a method.
I want to create my login form with autoforms and so I created a callback method which get called after a user submitted the login form. The form gets called the right way but the loginWithPassword function does not seems to work.
This is my method (on Client & Server side)
Meteor.methods({
autoform_test_login : function (doc) {
console.log('Called login method');
if (Meteor.isClient) {
Meteor.loginWithPassword('test', 'test', function(e) {
if (e) {
console.log(e);
}
});
}
}
});
My autoforms calls this method when submitting with:
{{#autoForm schema="Schema_Login" id="form_login" type="method" meteormethod="autoform_test_login"}}
....
When submitting this form I get this error:
Error: No result from call to login {stack: (...), message: "No result from call to login"}
When I now open my Browser console and type in:
Meteor.call('autoform_test_login');
I will get the same error.
But: When I type the following in my console it works (The error now is: Username not found):
Meteor.loginWithPassword('test', 'test', function(e) {
if (e) {
console.log(e);
}
});
My method do absolutely nothing else then this snipped so I am asking myself whats going wrong here.
Ps.:
I know that I added the "test" as Username and "test" as password - its just to test. Even when the input is the right the error is always the same.
Okay, so I got a response and now I know why this is not working as expected.
loginWithPassord may only be executed on the client.
When you use Meteor.methods on the client, it will still run the functions you define within it on the server. That is why it won't work to have the loginWithPassword call within a Meteor.methods function.
Simply use this function anywhere else on the client. For example - directly within some template event.
Took me like forever to find out why it wasn't working.
Make sure that autoform is actually passing the correct values. If you've made a mistake in you're schema setup it will automatically clean the values (set to undefined) without throwing an error.
I'm also not entirely sure if using it with method set will work in this case, as you want to do the login call on the client not the server (I think).
Make sure your current Meteor instance has an active connection with the mongo database pointed to by variable MONGO_URL. Meteor.loginWithPassword fails to give error feedback when this connection gets closed or broken.

Meteor Deps.Autorun know when data has been fully fetched

Is there a way to know when data has been initially fully fetched from the server after running Deps.autorun for the first time?
For example:
Deps.autorun(function () {
var data = ItemsCollection.find().fetch();
console.log(data);
});
Initially my console log will show Object { items=[0] } as the data has not yet been fetched from the server. I can handle this first run.
However, the issue is that the function will be rerun whenever data is received which may not be when the full collection has been loaded. For example, I sometimes received Object { items=[12] } quickly followed by Object { items=[13] } (which isn't due to another client changing data).
So - is there a way to know when a full load has taken place for a certain dependent function and all collections within it?
You need to store the subscription handle somewhere and then use the ready method to determine whether the initial data load has been completed.
So if you subscribe to the collection using:
itemSub = Meteor.subscribe('itemcollections', blah blah...)
You can then surround your find and console.log statements with:
if (itemSub.ready()) { ... }
and they will only be executed once the initial dataset has been received.
Note that there are possible ocassions when the collection handle will return ready marginally before some of the items are received if the collection is large and you are dealing with significant latency, but the problem should be very minor. For more on why and how the ready () method actually works, see this.
Meteor.subscribe returns a handle with a reactive ready method, which is set to true when "an initial, complete snapshot of the record set has been sent" (see http://docs.meteor.com/#publish_ready)
Using this information you can design something simple such as :
var waitList=[Meteor.subscribe("firstSub"),Meteor.subscribe("secondSub"),...];
Deps.autorun(function(){
// http://underscorejs.org/#every
var waitListReady=_.every(waitList,function(handle){
return handle.ready();
});
if(waitListReady){
console.log("Every documents sent in publications is now available.");
}
});
Unless you're prototyping a toy project, this is not a solid design and you probably want to use iron-router (http://atmospherejs.com/package/iron-router) which provides great design patterns to address this kind of problems.
In particular, take a moment and have a look at these 3 videos from the main iron-router contributor :
https://www.eventedmind.com/feed/waiting-on-subscriptions
https://www.eventedmind.com/feed/the-reactive-waitlist-data-structure
https://www.eventedmind.com/feed/using-wait-waiton-and-ready-in-routes

SignalR generate multiple executions

I'm building a search engine using SignalR to deliver partial responses in real time to the client.
The problem occurs when the first search is not over, and the client modifies the value of the textbox (txtTab) and click the button (btnSearch) again. The results of the two queries are mixed because the server keeps the two concurrent executions.
I need that when the client clicks the search button the previous execution is canceled.
Tried using hub.stop () and hub.disconnect (), but I can not.
Sorry my bad english :)
var busca = $.connection.hubBusca;
busca.client.atualizaResultados = function (arr) {
oTable.fnAddData(arr);
};
$.connection.hub.start().done(function () {
$('#btnSearch').click(function () {
if ($('#txtTab').val() != '') {
busca.server.iniciar($('#txtTab').val());
}
});
});
Thanks!
Luiz Fernando
I would suggest creating an additional server and client method to handle the final search (which happens when #btnSearch is clicked).
Instead of invoking busca.server.iniciar invoke something like busca.server.terminar.
I would also suggest setting some sort of boolean flag before calling busca.server.terminar to disable busca.client.atualizaResultados so no preliminary search results interfere with the final search results.
Then in HubBusca.Terminar you could call Clients.Caller.finalesResultados which would not be disabled unlike Clients.Caller.atualizaResultados.
In this way you can ensure that your final search results which are sent to the finalesResultados method will not be replaced by results sent to the atualizaResultados client method.
Sorry for my bad Spanish method names. I used Google Translate.

When is the "null" publish ready?

Having the following code on the server:
Meteor.publish(null, function(){
// Return some cursors.
})
will according to the documentation have the following effect: the record set is automatically sent to all connected clients.
How can I on the client side determine if all the documents published by this function has been received? If I would use a subscription instead, it would provide me with a ready callback, letting me know when all the documents been received. What's the matching way here? Or are the documents already received at the client when my client side code starts to execute?
I'm afraid there's no way to have a ready callback for so called universal subscriptions you mentioned above. Just have a look at this part of Meteor's code, where the publish and subscription logic is defined on the server. For convenience I'm copy/pasting the code below:
ready: function () {
var self = this;
if (self._isDeactivated())
return;
if (!self._subscriptionId)
return; // unnecessary but ignored for universal sub
if (!self._ready) {
self._session.sendReady([self._subscriptionId]);
self._ready = true;
}
}
The _subscriptionId is only given to named subscriptions, which are those that you would manually define using Meteor.subscribe method. The subscriptions corresponding to null publish functions, doesn't have their own _subscriptionId, so as you can see from the code above, the server is not event trying to send the ready message to the client.

Resources