javascriptmeteormeteor-helpermeteor-tracker

How to wait computation in meteor.helper until re-computation due to dependency change in template.autorun has been made?


I always getting this error when reactive variable change:

Exception in template helper: Error: $in needs an array
    at Error (native)
    at Object.ELEMENT_OPERATORS.$in.compileElementSelector (http://localhost:3000/packages/minimongo.js?cdf1a26cf7719fa9471a8017c3defd5aea812727:1827:15)
    at http://localhost:3000/packages/minimongo.js?cdf1a26cf7719fa9471a8017c3defd5aea812727:1509:19
    at Function._.each._.forEach (http://localhost:3000/packages/underscore.js?46eaedbdeb6e71c82af1b16f51c7da4127d6f285:157:22)
    at operatorBranchedMatcher (http://localhost:3000/packages/minimongo.js?cdf1a26cf7719fa9471a8017c3defd5aea812727:1489:5)
    at compileValueSelector (http://localhost:3000/packages/minimongo.js?cdf1a26cf7719fa9471a8017c3defd5aea812727:1393:12)
    at http://localhost:3000/packages/minimongo.js?cdf1a26cf7719fa9471a8017c3defd5aea812727:1372:9
    at Function._.each._.forEach (http://localhost:3000/packages/underscore.js?46eaedbdeb6e71c82af1b16f51c7da4127d6f285:157:22)
    at compileDocumentSelector (http://localhost:3000/packages/minimongo.js?cdf1a26cf7719fa9471a8017c3defd5aea812727:1355:5)
    at _.extend._compileSelector (http://localhost:3000/packages/minimongo.js?cdf1a26cf7719fa9471a8017c3defd5aea812727:1332:12)

I suspect the culprit is w (reactive variable)

Take a look at this:

Template.cList.onCreated(function(){
  var self = this;
  self.d = new ReactiveVar()
  self.w = new ReactiveVar()
  self.autorun(function() {
    var b = A.findOne(Pi());
    if (b && b.array) {
      var h = Subs.subscribe('B', b.array)
      self.d.set(h.ready()) // is subscription ready?
      self.w.set(b.array)
    }
  });
});

Template.cList.helpers({
  cLists: function () {
    if (Template.instance().d.get() && Template.instance().w.get()) {  // run only when d and w is ready
      return B.find({_id: {$in:Template.instance().w.get()}}, {fields: {title:1, src:1}});
    }
  }
});

Let's breakdown with step-by-step...

  1. First time no error
  2. When I change page, following dependency will change: Pi()
  3. Autorun will re-run.
  4. Because Pi() change, following variables will change: b && b.array && h && self.d.set(h.ready()) && self.w.set(b.array)
  5. I suspect cList is computed right after page change without waiting autorun re-computation is finished, that's why error is thrown.
  6. Right after autorun finished re-compute the dependendy change, cLists show correct list according to the change of dependency change. No issue in user interface indeed. But this warning looks dirty.

I guess to avoid warning above is to wait cList when dependency change. How do I do that? How do I wait computation in meteor.helper until re-computation due to dependency change in template.autorun has been made?


Solution

  • the culprit is ready callback from meteorhacks:subs-manager... change it with template subscription will avoid error...

    Template.cList.onCreated(function(){
      var self = this;
      self.d = new ReactiveVar()
      self.w = new ReactiveVar()
      self.autorun(function() {
        var b = A.findOne(Pi());
        if (b && b.array) {
          self.subscribe('B', b.array)
          self.w.set(b.array)
        }
      });
    });
    
    Template.cList.helpers({
      cLists: function () {
        if (Template.instance().subscriptionsReady() && Template.instance().w.get()) {  // run only when subscription and w is ready
          return B.find({_id: {$in:Template.instance().w.get()}}, {fields: {title:1, src:1}});
        }
      }
    });