meteor client async pattern / how to implement a waitOn for a list of subscriptions w callbacks

穿精又带淫゛_ 提交于 2019-12-11 22:21:20

问题


for various reasons I'm writing an app that doesn't use IronRouter, but has to implement some similar logic. One is waiting for a list of subscriptions to be ready.

Since this is an async call client side in meteor, what are some techniques for doing this?

If I want to have a list of subs like:

  sublist = [
    PubSubMan.subscribe("Players"),
    PubSubMan.subscribe("Stuff")
  ]

then start with the rest of the app once they are all .ready() = true

what is a good way to do this?

I can't quite understand how the wait() method is implemented in the IR source code here

This seems an ideal case for an aysnc.js type situation, where I want to call a list of methods and continue when their callbacks are done, but resorting to node style patterns seems a bit clunky for meteor. I looked at wrapAsync and meteorhacks async utils but that seems mostly for server methods and wrapping NPM packages.

If I could sum the list of ready() values and then create a Tracker deps that would fire if/when that sum changed... ? but not quite sure how to do that either.

Since each of the subscriptions fires a callback when done, i guess i could use a counter to track when callbacks are fired and keep a counter to check == length of the array, but again that seems kind of inelegant.

EDIT: This isn't an ideal solution but the below works. But I still think I'm missing a more elegant method.

  subList = [
    PubSubMan.subscribe("Players"),
    PubSubMan.subscribe("Stuff" )
  ]

  Tracker.autorun (c) =>
    subReady = _.filter subList, (item) ->
      return item.ready()
    allDone = (subList.length == subReady.length)
    console.log("subs status: #{subReady.length} / #{subList.length} = ready: #{allDone}")
    if allDone
      c.stop()
      startMainLoop()

related to this question on how tracker.autorun picks its computation dependencies how does Tracker.autorun pick out its computation?


回答1:


I'm not sure what your startMainLoop is like, but here's an approach that might work for you. Create a new template which just checks if all the subscriptions are ready; if they are it renders the real main template, and if they aren't then it renders a loading template.

<template name="subscriptionsReadyCheck">
  {{#if allSubsAreReady}}
    {{> mainTemplate}}
  {{else}}
    {{> loadingTemplate}}
  {{/if}}
</template>
subList = [...]

Template.subscriptionsReadyCheck.helpers {
  allSubsAreReady: -> _.every(subList, (sub) -> sub.ready())
}

This assumes that the subscriptions are created when the page loads and stays around until the page is closed. If you need subscriptions which are only created when the template is rendered and are stopped when the template is destroyed, you can store them on the template instance:

Template.subscriptionsReadyCheck.created = ->
  @subList = [...]

Template.subscriptionReadyCheck.destroyed ->
  for sub in @subList
    sub.stop()

Template.subscriptionsReadyCheck.helpers {
  allSubsAreReady: -> _.every(Template.instance().subList, (sub) -> sub.ready())
}


来源:https://stackoverflow.com/questions/26353852/meteor-client-async-pattern-how-to-implement-a-waiton-for-a-list-of-subscripti

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!