简体   繁体   English

流星Sub / Pub with Simulation,其中发布缓慢更新

[英]Meteor Sub/Pub with Simulation where pub is slow to update

I have a pub that wraps and external API. 我有一个包装和外部API的酒吧。 Client subs the external api pub. 客户端订阅了外部api pub。 There is a 'ACTIVATE' button they can push to activate a billing method. 他们可以按下“激活”按钮来激活计费方式。 Button calls an update method that updates the collection. 按钮调用更新集合的更新方法。 The pub updates the external api. 酒馆会更新外部api。 Simulation runs and updates the client collection. 模拟运行并更新客户端集合。 Button changes to 'DEACTIVATE' as expected. 按钮将按预期方式更改为“停用”。 This is where the issue comes in. The external api takes some time to return with the updated doc. 这就是问题所在。外部api需要一些时间才能返回更新的文档。 Within 100-200ms of the button turning to 'DEACTIVATE' it will flip back to 'ACTIVATE' and then 500ms latter back to 'DEACTIVATE' where it should be assuming there were no issues with the external api. 在按钮变为“停用”的100-200毫秒内,它将翻转回“激活”,然后在500毫秒后回到“停用”,这应该假设外部api没有问题。

I'm sure I could come up with some hacky solution to deal with this in the client but wondering if there is a way to tell the simulation/client collection that the pub is slow and to not update quite as often? 我确定我可以提出一些骇人听闻的解决方案来解决客户端中的此问题,但想知道是否有一种方法可以告诉模拟/客户端集合发布速度很慢并且更新的频率不那么高? Thus, giving the pub/external api more time to complete it's updates. 因此,给pub / external API更多的时间来完成更新。

This turned out to be really simple. 事实证明这很简单。

Client side simulation alone is not enough. 仅客户端仿真是不够的。 The trick is to do server side simulation as well. 技巧是同时进行服务器端仿真。 To accomplish this first setup a hook to the Meteor.publish this object something like this. 要完成此操作,首先需要设置Meteor的钩子。

_initServer() {
  if (Meteor.isServer) {
    console.log(`Server initializing external collection "${this.name}"`)
    let self = this

    Meteor.publish(this.name, function (selector, options) {
      check(selector, Match.Optional(Match.OneOf(undefined, null, Object)))
      check(options, Match.Optional(Match.OneOf(undefined, null, Object)))

      self.publication = this
      self._externalApi.fetchAll()
        .then((docs)=>docs.forEach((doc)=>this.added(self.name, doc._id, doc)))
        .then(()=>this.ready())
        // todo handle error
        .catch((error)=>console.error(`${self.name}._initServer: self._externalApi.fetchAll`, error))
    })
  }
}

Then in your update function you can simulate on both the client and server like so: 然后,在更新功能中,您可以在客户端和服务器上进行模拟,如下所示:

  this.update = new ValidatedMethod({
    name: `${self.name}.update`,
    validate: (validators && validators.update) ? validators.update : self.updateSchema.validator({clean: true}),
    run(doc) {
      console.log(`${self.name}.update `, doc)
      if (Meteor.isServer && self._externalApi.update) {
        // server side simulation
        self.changed(doc)

        self._externalApi.update(doc._id, doc)
          .then(self.changed)
          .catch((error)=>handleError(`${self.name}.update`, 'externalApi.update', error))
      } else {
        // client side simulation
        self.collection.update(doc._id, {$set: doc})
      }
    },
  })

Apologizes if this is over simplified these examples are from a large library we use for external api's. 抱歉,如果这过于简化,则这些示例来自我们用于外部api的大型库。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM