New to Meteor. About Methods, call server only function, confused


#1

Hi there,

I’m new to Meteor & trying to play with the methods. I’m trying to call a server only function inside one method.

Let’s say I would like to return user by username but wouldn’t want to expose all users db to the client.

Meteor.methods({
test(username){
check(username, String);
let user = Accounts.findUserByUsername(username);
console.log(user);
return user;
}
});

Meteor.call(‘test’,‘mmommo’);

from server side, it prints the user object. But the client side I got the error which is pretty much expected for I knew Accounts is server only.

Exception while simulating the effect of invoking ‘test’ TypeError: Accounts.findUserByUsername is not a function(…) TypeError: Accounts.findUserByUsername is not a function

Any idea about how to design a pattern for similar situation?

Many Thanks!


#2

Here you have a guide thats decribe methods:

http://meteortips.com/first-meteor-tutorial/methods/


#3

You can leverage a Methods isSimulation property to control what get’s called on the server. With Meteor 1.3.3 you can now also dynamically import any server only files, as needed (you had to use require before Meteor 1.3.3). A quick example:

/imports/methods.js

import { Meteor } from 'meteor/meteor';

Meteor.methods({
  randomMessage() {
    if (!this.isSimulation) {
      import { generateRandomMessage } from './message_generator';
      return generateRandomMessage();
    } else {
      console.log('In the client stub - not doing anything ...');
    }
  }
})

/imports/message_generator.js

export const generateRandomMessage = () => {
  return `Something random from the server --> ${Math.random()}`;
};

/client/main.js

import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
import { Meteor } from 'meteor/meteor';
import '/imports/methods';
import './main.html';

Template.body.onCreated(function onCreated() {
  this.randomMessage = new ReactiveVar();
});

Template.body.helpers({
  randomMessage() {
    return Template.instance().randomMessage.get();
  },
});

Template.body.events({
  'click button'(event, instance) {
    Meteor.call('randomMessage', (error, result) => {
      instance.randomMessage.set(result);
    });
  },
});

/client/main.html

<body>
  <h1>Welcome to Meteor!</h1>
  <button>Click Me</button>
  <p>Random message: {{randomMessage}}</p>
</body>

/server/main.js

import '/imports/methods';

#4

Thanks for the explanation. I’ve red danjimagar’s link before. It actually doesn’t talk about invoke server side functions, only db operations which is quite similar to official task tutorial. From the example I described above, it’s actually another function which is server only. hwillson provided a very useful example. But it does nothing on client side which we might still want the client retrieve the user information for the example I gave.

The scenario is:

  • We have a server only function Accounts.findUserByUsername()
  • We want the client make the call. Meteor.call().
  • The server will do some checking. If the client is allowed to receive the information, call the server side only function & return value, otherwise return null.

What’s the best way to achieve the task? This wouldn’t be a question for any other frameworks but here I’m really confused.

Many Thanks!


#5

The very confusing part is, the Meteor client is expecting every result instantly so there’s no buffer time for server to check & do computations and then return value.

Meteor provided examples about exposing some db parts to the client to make the results ‘predictable’, but there’s lots of situation when the results are non-predictable.


#6

How about using callback? When username is already taken, throw error