如何在从 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 返回之前等待子流程结果的主要内容,如果未能解决你的问题,请参考以下文章

在从函数返回之前等待 Firebase 加载

如何确保在从 Mongoose 中的函数返回之前执行异步调用?

Meteor:ArrayBuffer(FileReader 结果)未传递给 Meteor.method()

函数等待返回直到 $.getJSON 完成

如何在继续之前等待 requestLocation?

如何在构建有状态小部件之前等待功能? [复制]