简体   繁体   中英

How to wait for sub process results before returning from Meteor.method

I'm kinda surprised that the Meteor.method definitions require a result to be returned rather than a callback be called. But so it is!

I'm trying to make an RPC method in Meteor that calls mongoose group methods (It didn't look like meteor's data api lets me do it so I'm working around it). I have something like this:

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.

My own variation of the code posted above does work...I get calls from my meteor client, the mongoose objects all work their magic. But I can't figure out how to get my results to return within the original context.

How can I do this?


The answer I went with would make my code look like this:

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

Ah...figured it out. After googling and googling and finding inordinate numbers of comments along the lines of "don't do it that way, use callbacks!", I finally found it: use fibers !

I ended up using the fibers-promise library. My final code looks something like this:

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

通过一系列示例查看这个惊人的要点

Using the fibers/future module may give you a better API for Meteor as this is what is used internally, and it comes with any vanilla meteor install.

To take your example:

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()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM