如何在从 Meteor.method 返回之前等待子流程结果
Posted
技术标签:
【中文标题】如何在从 Meteor.method 返回之前等待子流程结果【英文标题】:How to wait for sub process results before returning from Meteor.method 【发布时间】:2012-05-02 07:52:51 【问题描述】:我有点惊讶Meteor.method
定义需要返回结果而不是调用回调。但事实就是如此!
我正在尝试在 Meteor 中创建一个调用 mongoose 组方法的 RPC 方法(看起来流星的数据 api 不允许我这样做,所以我正在解决它)。我有这样的事情:
Meteor.methods
getdata: ->
mongoose = __meteor_bootstrap__.require('mongoose')
db = mongoose.connect(__meteor_bootstrap__.mongo_url)
ASchema = new mongoose.Schema()
ASchema.add(key: String)
AObject = mongoose.model('AObject',ASchema)
AObject.collection.group(
...
...
(err,doc) -> # mongoose callback function
# I want to return some variation of 'doc'
)
return ??? # I need to return 'doc' here.
我自己对上面发布的代码的变体确实有效...我接到了来自我的流星客户端的电话,猫鼬对象都发挥了它们的魔力。但我不知道如何让我的结果在原始上下文中返回。
我该怎么做?
我的答案会让我的代码看起来像这样:
require = __meteor_bootstrap__.require
Meteor.methods
getdata: ->
mongoose = require('mongoose')
Future = require('fibers/future')
db = mongoose.connect(__meteor_bootstrap__.mongo_url)
ASchema = new mongoose.Schema()
ASchema.add(key: String)
AObject = mongoose.model('AObject',ASchema)
group = Future.wrap(AObject.collection.group,6)
docs = group.call(AObject,collection,
...
...
).wait()
return docs
【问题讨论】:
【参考方案1】:啊……想通了。在谷歌搜索和谷歌搜索并按照“不要那样做,使用回调!”的思路找到过多的 cmets 之后,我终于找到了它:使用fibers!
我最终使用了fibers-promise 库。我的最终代码如下所示:
Meteor.methods
getdata: ->
promise = __meteor_bootstrap__.require('fibers-promise')
mongoose = __meteor_bootstrap__.require('mongoose')
db = mongoose.connect(__meteor_bootstrap__.mongo_url)
ASchema = new mongoose.Schema()
ASchema.add(key: String)
AObject = mongoose.model('AObject',ASchema)
mypromise = promise()
AObject.collection.group(
...
...
(err,doc) -> # mongoose callback function
if err
mypromise.set new Meteor.Error(500, "my error")
return
...
...
mypromise.set mydesiredresults
)
finalValue = mypromise.get()
if finalValue instanceof Meteor.Error
throw finalValue
return finalValue
【讨论】:
你可以接受你自己的答案,我认为这是合理的。不过,您可能需要先等待一段时间。 很抱歉 - 我在那里兴奋了一分钟,无法自拔。 我不是在抱怨,我建议您接受自己的答案,以便将来的搜索者更容易解决类似问题。 哦,对了,呵呵。好吧,再过 2 天我不会这样做,但我会的,谢谢。【参考方案2】:使用fibers/future 模块可能会为您提供更好的Meteor API,因为这是内部使用的API,并且它随任何香草流星安装一起提供。
以你为例:
require = __meteor_bootstrap__.require
Future = require 'fibers/future'
mongoose = require 'mongoose'
Meteor.methods
getdata: ->
db = mongoose.connect(__meteor_bootstrap__.mongo_url)
ASchema = new mongoose.Schema()
ASchema.add(key: String)
AObject = mongoose.model('AObject',ASchema)
# wrap the method into a promise
group = Future.wrap(AObject.collection.group)
# .wait() will either throw an error or return the result
doc = group(... args without callback ...).wait()
【讨论】:
听起来不错,我试试看。 如果你尝试 doc = group.call(AObject.collection, ...args without callback...).wait() 而不是 doc = group(...args without callback... ).wait(),你还会遇到同样的异常吗? Arg,抱歉跑来跑去。所以我发布的第一个错误 (Object # 'requires no more than -1 arg'的错误很常见。这是因为您在没有参数的情况下调用了包装的方法。在这些情况下,您需要将要包装的方法的数量作为第二个参数:Future.wrap(Aboject.collection.group, 0)... 其中 0 是函数的数量(因为它需要 0 个参数和回调 - 根据需要进行更改)。 TypeError ('has no method...) 听起来 this 的值未设置为您期望的值,这就是为什么我建议执行 find.call(AObject, args...) 之类的操作。我希望这会有所帮助,我需要查看/与您的代码交互以更进一步...... 谢谢,我让它工作了,因为它不需要创建额外的包,所以我选择它。【参考方案3】:查看this amazing gist 的示例集合。
【讨论】:
Always quote the most relevant part of an important link, in case the target site is unreachable or goes permanently offline.以上是关于如何在从 Meteor.method 返回之前等待子流程结果的主要内容,如果未能解决你的问题,请参考以下文章
如何确保在从 Mongoose 中的函数返回之前执行异步调用?