如何在从 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 #...) 是当我试图包装一个“AObject.find”调用时。我尝试将 AObject 传递给它,但运气不佳(上面的错误类型相同)。然后我尝试了 AObject.collection.group,就像我在帖子中写的那样,它给了我这个错误:函数期望不超过 -1 个参数。我尝试将 AObject.collection 作为参数放入并得到相同类型的错误。 '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 返回之前等待子流程结果的主要内容,如果未能解决你的问题,请参考以下文章