Why is Meteor.methods inside Meteor.startup?


#1

Are there any consequences of not having Meteor.methods inside of the Meteor.startup?

as I often see

Meteor.startup( () => {

Meteor.methods({
});

}

or is it best practice ?


#2

I don’t think so… putting them in startup() prevents you from using methods that need to run when the client/server starts because it’s only fired once it has finished loading.


#3

Hi reoh, so you are saying that server-side methods with MongodB access should be inside Meteor.methods, which in turn should be inside Meteor.startup?


#4

There is usually no need to do that inside startup.

Defining things in startup is a “cheat” to get around poor load order control in meteor. However in 1.3 you have access to full modules, so you have better control of that, and then your dependency controls your load order which obviates the need for this practice. Usually you want to define methods directly (not in startup), and call certain ones in startup functions. The methods defined outside of startup functions will be guaranteed to have been defined by the time you hit startup. (They’re in the “definitions” phase as it were)


#5

Hi lassombra, but if you say that methods are defined outside of startup, then doesnt this mean that there will be less of a guarantee than something which is defined inside startup???


#6

No, I’m saying not to do that.

// file.js

// top-level
Meteor.methods({
  foo () {
    // code
  }
});

// startup callback
Meteor.startup(function () {
  Meteor.methods({
    bar () {
      // code
    }
  });  
});

// This will work
Meteor.call('foo');

// This won't because it hasn't been defined yet
Meteor.call('bar');

Meteor.startup(function () {
  // This will work ONLY if the previous startup call was loaded before this one
  // (it's also what @lassombra was talking about)
  Meteor.call('bar');
});

#7

^^^^^^ that

basically methods defined at top level are guaranteed to be defined before startup. The application cycle goes through a simple sequence (this is true of all javascript, not just Meteor fyi)

  1. Definition/parsing. Anything in top level scope will run at this point in time, whether it is IIFEs or just simple expressions, they will all run at this point in time. Because javascript is single threaded, you can always be assured (aside from hoisting mechanics which are an important topic and a good read) that your file will be run top to bottom.
  2. Startup. In plain javascript this is the window.onLoad() callback. In jQuery it is the contents of $(function) call. In Meteor this is all the various startup code blocks. Thing is these by definition have to come after phase 1 as phase 1 is how you schedule things to happen in phase 2
  3. Event Loop. This is your running application. It exists out in user land for a potentially very long time. There is a lot of good information about this, but my favorite is what is the event loop anyways? which is quite entertaining to say the least…
  4. Teardown. You usually have no control over this. Technically in Node.js world you can write c++ plugins which do, but let’s assume for the moment that you don’t have any control over this. This is the unspooling of the event loop and the forcible freeing of memory allocated by your application.

All together, this means that your methods should be defined outside of startup, while your initial method calls should be defined in startup blocks. That way you have 100% assurance that they are defined and ready to be used! (Note, method calls in routers/as a result of events are always in phase 2/3.


#8

Just to add: I have never put Meteor.methods() into Meteor.startup(). Can’t even think of what that should be good for. As far as I can tell that’s just silly. Meteor.methods is code that defines methods (duh), and such code is always placed in the outermost scope, whether you’re working with Meteor and defining these particular methods or if it’s plain old regular javascript functions. Top-level. (Or working with Java or C++ or what have you – you may put function/method definitions into some sort of namespace, but aside from that it’s at the top level generally.)


#9

Me neither, but I’ve seen it done.[quote=“seeekr, post:8, topic:22063”]
Can’t even think of what that should be good for.
[/quote]

It was often presented (pre Meteor 1.3) as a solution to load order. Just don’t depend on load order, by waiting until Meteor.startup everything has loaded. It’s not good practice, but it works in a few small applications.

Basically it’s all a question of when the code loads, and in the case of Meteor.methods it should be at definition time I believe (what you refer to as top-level).


#10

I have made a bunch of apps and have never put anything inside Meteor.startup() before and that hasn’t prevented anything from working…


#11

Cheers guys so helpful to know.


#12

It may have been presented as a solution to load-order problems, but it simply is not. (Keep in mind that there are a lot of newbie programmers learning JS and Meteor, and so while the learning and questioning and answering is happening, there will be a lot of inaccurate code and (speculative) explanations being posted. Which is fine, it’s a learning process, but it’s important to know when not to take everything at face value and do your own thinking and understanding.)
For code that actually does something and depend on load order, yes, putting it in Meteor.startup() can potentially help. But for Meteor.methods() alone – nope, that will not do anything at all.

If you’re not convinced try coming up with an example of a bit of code that breaks when Meteor.methods() is not inside Meteor.startup() and works when it is. $10 if you can teach me something new by showing me how my knowledge and thinking here was limited. :wink:

(But basically it’s like saying “defining a method later instead of immediately is better in some cases” – nope; method definition is by definition not code that is executed when it is encountered by the (JIT-)compiler/interpreter, but it is rather the idea of giving a name to a chunk of code that will be executed when it is invoked from another piece of code… for that latter part it makes sense to think about when that is going to be. For the former (method definition) the earlier a method is defined, the better, so any other code can depend on it (call the method) earlier. All of this could be phrased a lot more accurately and examples in JS and ideally one more (compiled) language would certainly help illustrate this issue even better. But I hope even as is a bit of “programming wisdom” comes across!)


#13

wow… long winded reply to my statement.

I was in no way advocating this technique, simply answering the implied question about when the hell anyone would use it.

I have never used it, and I would never use it. I can’t think of a single case (because there isn’t one) where it is the better solution. There are however cases where it works and some people have gotten away with it in very small applications. I on the other hand maintain an application that is currently about 17k lines of code. If I had done that, even once, I’m sure it would have been a shot in my own foot! The moment I had load order problems, I went headfirst into package architecture, and haven’t looked back until 1.3 modules which are about damn time in my opinion.


#14

I see. I have a method that is running during startup and it is coming up as undefined. As I’m using 1.3, I can just import that file with the method to the file that is running on startup and I should have access to it? Or should I put that specific method inside a meteor.startup?


#15

I would guess that the method you’re defining is probably under an imports/ folder somewhere, and you’re failing to import it into your app. I have found myself using Meteor.startup less and less with import and export.


#16

@streemo : agreed. I only seem to use startup for defining indexes and occasionally pre-loading the database - and let’s be honest, it’s not actually necessary for those use cases.