gpt4 book ai didi

meteor - 如何防止 Meteor.userId() 和依赖于 userId 的订阅更新之间的客户端竞争条件?

转载 作者:行者123 更新时间:2023-12-02 01:47:55 35 4
gpt4 key购买 nike

我看到一个可重复的问题,用户使用 Meteor 服务器进行身份验证(“登录”),然后是依赖于 userId 的客户端订阅之前更新(并且相关 UI 模板 react 性更新)Meteor.userId()注册登录成功。

例如,在此代码片段中,断言将为 throw :

var coll = new Meteor.Collection("test");

if (Meteor.isServer) {
Meteor.publish('mineOrPublic', function () {
// Publish public records and those owned by subscribing user
return coll.find({owner: { $in: [ this.userId, null ]}});
});
}

if (Meteor.isClient) {
var sub = Meteor.subscribe('mineOrPublic');
var cursor = coll.find({});
cursor.observe({
added: function (doc) {
if (doc.owner) {
// This should always be true?!
assert(doc.owner === Meteor.userId());
}
}
});
}

类似于 added上面的函数,如果我写一个模板助手来检查 Meteor.userId() , 它会看到 null 的值,即使它是通过具有所有者的文档的数据上下文调用的。

Meteor 集合 Pub/Sub 和帐户之间显然存在竞争条件 userId更新机制。在我看来Meteor.userId()应始终在根据 this.userId 中的更改任何订阅更新之前进行更新在服务器发布功能中,但由于某种原因,相反的情况通常似乎是正确的(即,上面代码中的 assert 通常会抛出)。

我关心的原因是因为我有依赖于在客户端上获取有效的 Meteor 身份验证 token (使用 Accounts._storedLoginToken() )的软件包,用于保护对存储在 Meteor 服务器上的文件的 HTTP 请求。并且身份验证 token 在 Meteor.userId() 之前是不正确的是。所以事件的流程通常是这样的:

  • 用户登录
  • 服务器上的发布功能根据 this.userId 中的更改重新运行.
  • 客户端开始接收与 userId 更改相对应的新文档。
  • UI 模板响应式更新以添加由新文档驱动的 DOM 元素
  • 一些 DOM 元素是 <img>带有 src= 的标签取决于数据上下文的值。
  • HTTP 请求被触发并最终以 403 失败(禁止)错误,因为尚未设置所需的身份验证 cookie。
  • Meteor.userId()最终在客户端更新,代码响应式运行以设置身份验证 cookie
  • 模板中依赖于 cookie 更新代码中设置的 session 变量的帮助程序将重新运行,但 DOM 不会更改,因为 <img> 中的 URLs标签不会改变。
  • 因为 DOM 没有改变,标签不会重试它们失败的图像加载尝试。
  • 一切都安定下来,用户必须手动重新加载页面才能显示他们的图像。

我想出了两种可能的方法来解决这个问题:

  1. 在为 <img> 生成 URL 的模板助手中标记,始终附加一个虚拟查询字符串,例如:"?time=" + new Date().getTime() .这会导致每次调用帮助程序时 DOM 都会更改并解决问题,但它会搞砸浏览器缓存,如果不协调,将导致某些 Assets 不必要地加载多次等。

  2. 在每个涉及文档数据的模板助手中添加一个测试:

    if (this.owner && this.owner !== Meteor.userId()) { 
    // Perhaps Meteor.loggingIn() could be used above?
    // Invalid state, output placeholder
    } else {
    // Valid state, output proper value for template
    }

我真的希望有人知道解决这个问题的不那么笨拙的方法。或者,如果一致认为这是一个错误,并且 Meteor 的行为在这方面是不正确的。我会很乐意在 Github 上提交问题。我非常喜欢与 Meteor 一起工作,但这是一种坚韧不拔的烦恼,在“它能正常工作”的齿轮中磨磨蹭蹭。

感谢您提供的所有见解。

最佳答案

在尝试了很多事情之后,OP 中示例代码的这种变体似乎始终如一地解决了竞争条件,我发现这是一个可以接受的解决方案,这与我最初尝试的解决方法不同。

我仍然觉得这种逻辑应该是不必要的,欢迎其他方法或意见来判断 OP 示例代码中 Meteor 的行为是正确的还是错误的。如果评论中一致认为 Meteor 的行为是错误的,我将为此在 Github 上创建一个问题。

感谢任何其他反馈或替代解决方案。

var coll = new Meteor.Collection("test");

if (Meteor.isServer) {

Meteor.publish('mineOrPublic', function (clientUserId) {
if (this.userId === clientUserId) {
// Publish public records and those owned by subscribing user
return coll.find({owner: { $in: [ this.userId, null ]}});
} else {
// Don't return user owned docs unless client sub matches
return coll.find({owner: null});
}
});
}

if (Meteor.isClient) {

Deps.autorun(function () {
// Resubscribe anytime userId changes
var sub = Meteor.subscribe('mineOrPublic', Meteor.userId());
});

var cursor = coll.find({});

cursor.observe({
added: function (doc) {
if (doc.owner) {
// This should always be true?!
assert(doc.owner === Meteor.userId());
}
}
});
}

此代码的工作原理是向服务器发布功能提供它在客户端自己的登录状态之前运行时需要识别的信息,从而打破竞争条件。

我认为这是 Meteor 应该自动完成的事情:客户端不应该在发布函数中看到基于 this.userId 更改的文档,直到客户端 Meteor.userId() 已更新。

其他人同意吗?

关于meteor - 如何防止 Meteor.userId() 和依赖于 userId 的订阅更新之间的客户端竞争条件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24445404/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com