问题
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