【问题标题】:Meteor, Cursor not staying in sync with Collection流星,光标与收藏不同步
【发布时间】:2014-02-19 01:57:36
【问题描述】:

我正在使用一些表单输入来创建一个新的Student,代码如下:

var student_id = Students.insert({firstname: firstInput, lastname: lastInput, price: priceInput});
Meteor.users.update({_id: Meteor.userId()}, {$push: {'student_ids': student_id}});

我设置了以下订阅和发布:

// On the client.
Meteor.subscribe('currentUser');

// On the server.
// I know this is ugly, but I need to do quite a bit of joining.
Meteor.publish('currentUser', function() {
    if (!this.userId) return;
    var userCursor = Meteor.users.find({_id: this.userId}, { fields: {firstname: true, lastname: true, student_id: true, student_ids: true, payment_ids: true, phones: true }});
    var user = userCursor.fetch()[0];
    if (user.student_ids || user.payment_ids) {
        var student_ids = user.student_ids || [];
        var studentCursor = Students.find({_id: {$in: student_ids}});

        var payment_ids = user.customer.payment_ids || [];
        var paymentCursor = Payments.find({_id: {$in: payment_ids}});

        var lesson_ids = [];
        var expense_ids = [];
        studentCursor.forEach(function(doc) {
            lesson_ids.concat(doc.lesson_ids);
            expense_ids.concat(doc.expense_ids);
        });
        var lessonCursor = Lessons.find({_id: {$in: lesson_ids}});
        var expenseCursor = Expenses.find({_id: {$in: expense_ids}});

        return [userCursor, studentCursor, lessonCursor, expenseCursor, paymentCursor];
    }
    else return userCursor;
});

问题是我的{{#each}} 块之一列出了所有这些学生,并且工作正常,除了在页面刷新/重新启动等之前它不会显示新学生。发布/订阅对没有反应。

我不确定如何优雅地解决这个问题。我绝对不想在发布函数中使用added 和其他此类回调。看来我的收藏应该自己处理这种行为。

提前致谢!

更新

我将发布更改为使用 publish-with-relations,这是一个反应式连接包,现在看起来像这样:

Meteor.publish('currentUser', function() {
    var studentMappings = [{
        key: 'lesson_ids',
        collection: Lessons,
    },{
        key: 'expense_ids',
        collection: Expenses,
    }];

    return Meteor.publishWithRelations({
        handle: this,
        collection: Meteor.users,
        filter: this.userId,
        options: { fields: {firstname: true, lastname: true, student_id: true, student_ids: true, payment_ids: true, phones: true }},
        mappings: [{
            key: 'student_id',
            collection: Students,
            mappings: studentMappings
        },{
            key: 'student_ids',
            collection: Students,
            mappings: studentMappings
        },{
            key: 'payment_ids',
            collection: Payments,
        }]
    });
});

所有内容都已发布,但仍不是反应式的!当页面重新加载时,一切都如预期的那样,但在添加新学生后,该学生所在的位置只会闪烁(我怀疑这是工作中的延迟补偿)。

当我在控制台查询Meteor.user()时,student_ids数组是正确的:

student_ids: Array[1]
    0: "5dafpCD7XGcBnyjWd"
  length: 1

当我meteor mongo这个时:

meteor:PRIMARY> db.students.find()
{ "firstname" : "Sterling", "lastname" : "Archer", "price" : "22.50", "_id" : "5dafpCD7XGcBnyjWd" }

一切也都是正确的,但在页面刷新之前文档仍然没有显示。

publish-with-relations 不是应该解决这个问题吗?

【问题讨论】:

    标签: meteor


    【解决方案1】:

    发布函数不是反应式的。即使用户文档发生更改,发布也不会重新运行并将学生文档发送到客户端。您需要的是反应式连接。实用解决方案见this answer,进一步启发见this post

    更新

    根据下面的 cmets,这里是关于如何根据用户的更改触发发布的建议。请注意,您实际上不必在发布函数中对 student_ids 执行任何操作 - 它只是为了触发对该键更改的订阅。

    Tracker.autorun(function() {
      if (Meteor.user()) {
        Meteor.subscribe('students', Meteor.user().student_ids);
      }
    });
    

    【讨论】:

    • 我没有发现您的 PWR 代码有任何明显错误。如果没有其他发布者向客户端发送相同的数据,并且客户端启动时数据就在那里,那么这是一个好兆头。问题可能像允许/拒绝规则这样简单吗?添加新学生时,直接检查数据库时是否在用户的 student_ids 数组中看到他/她($ meteor mongo)?
    • 我愿意。学生在数据库中正确,id 在student_ids 数组中正确。如果我在添加学生后立即刷新页面,一切都会正确显示,我认为这表明发布只要再次运行就可以工作。这可能与我安装软件包的方式有关吗?
    • 我怀疑这是一个包安装问题。我会看看我是否可以用你给出的代码来重现这个。我需要先完成一个项目 - 给我一两个小时。
    • 没问题,我非常感谢您的帮助,让我不那么苛刻!哈哈
    • 我在答案中添加了一个建议,这应该比在插入后手动调用 subscribe 更好(恶心)。至于 PWR,你可以尝试在 fork 中修复 bug。我一直在大力游说核心开发人员在 1.0 中加入库,因此希望这将是一个改进的替代方案。
    猜你喜欢
    • 2013-05-23
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-16
    相关资源
    最近更新 更多