流星方法的反应性不起作用

时间:2015-06-26 16:23:55

标签: javascript meteor

我在Javascript方面没有经验,但我已经阅读了大量有关Meteor反应性的文章,但仍然无法弄清楚为什么它在我的情况下不起作用。

当添加新产品时,我希望重新计算总成本并在totalCost帮助器中使用它,这样它几乎可以在浏览器中实时显示。

有人可以看看我的代码并试图找出一些逻辑错误吗?除了反应性之外的所有东西都在我的电脑上运行。

我在/models/Product.js中有这个方法:

Meteor.methods({
    totalProductCost: function() {
      var pipeline = [
        {$match: {owner: Meteor.userId()}},
        {$group: {_id: null, cost: {$sum: "$cost"}}}
      ];
      var data = Products.aggregate(pipeline)["0"].cost; 
      return (data === undefined) ? 0 : data;
    }
  });

然后我在客户端文件夹中有layout.js:

if (Meteor.isClient) {

    var handle = Meteor.subscribe("Products", Meteor.userId());

    ProductManager = {
        _productItems: null,
        _dep: new Tracker.Dependency(),

    getProducts: function () {
        this._dep.depend();
        return this._productItems;
    },

    setProducts: function (value) {
        if (value !== this._productItems) {
            this._productItems = value;
            this._dep.changed();
        }
    },

    getTotalCost: function () {
            return ReactiveMethod.call('totalProductCost');
        }
    }

    // TRACKER

    Tracker.autorun(function () {
        if (handle.ready()) {
            ProductManager.setProducts(Products.find().fetch());
        }
    });

    // HELPERS

    Template.boxOverview.helpers({
        "totalCost" : function () {
            return ProductManager.getTotalCost();
        },
    });
}

1 个答案:

答案 0 :(得分:0)

您似乎在方法中使用了collection.aggregate。如果需要反应性,则需要使用发布而不是方法(或者每次要刷新时都需要调用该方法)。但是,如果您在出版物中使用聚合(我假设为you use a package for it),您也会失去反应性。

我建议您使用没有aggregate功能的出版物。您可以通过创建新字段并将其添加到光标来计算产品成本。一旦你这样做,如果你想保持反应性,就必须使用cursor.observeChanges()cursor.observe()

看一下这个例子:

var self = this;

// Modify the document we are sending to the client.
function filter(doc) {
  var length = doc.item.length;

  // White list the fields you want to publish.
  var docToPublish = _.pick(doc, [
      'someOtherField'
  ]);

  // Add your custom fields.
  docToPublish.itemLength = length;

  return docToPublish;                        
}

var handle = myCollection.find({}, {fields: {item:1, someOtherField:1}})
            // Use observe since it gives us the the old and new document when something is changing. 
            // If this becomes a performance issue then consider using observeChanges, 
            // but its usually a lot simpler to use observe in cases like this.
            .observe({
                added: function(doc) {
                    self.added("myCollection", doc._id, filter(doc));
                },
                changed: function(newDocument, oldDocument)
                    // When the item count is changing, send update to client.
                    if (newDocument.item.length !== oldDocument.item.length)
                        self.changed("myCollection", newDocument._id, filter(newDocument));
                },
                removed: function(doc) {
                    self.removed("myCollection", doc._id);                    
                });

self.ready();

self.onStop(function () {
  handle.stop();
});

这取自here