hharnisc / python-meteor

A meteor client for python
MIT License
157 stars 27 forks source link

[Question] why just the first element of parameters in client.call have effect? #15

Closed wuxianliang closed 9 years ago

wuxianliang commented 9 years ago

Dear @hharnisc and @ppettit

When I execute the following code, just 'a' appears in terminal, I can't understand why the other parameters do not appear.

    client.call('callPy', ['a', 'b',  'c'])
    Meteor.methods({
        callPy: function(x){
            console.log(x)
            return 'abc'
            }
    })

After I tried several other codes. I found the following code works, 'b' appears.

client.call('callPy', [['a', 'b',  'c']])
    Meteor.methods({
        callPy: function(x){
            console.log(x[2])
            return 'abc'
            }
    })

Though 'b' appears nearly every time, the exception ocasionlly appears too.

Exception in thread WebSocketClient (most likely raised during interpreter shutdown)

Is there a reliable way to call Meteor.methods with parameters? Thank you very much!

ppettit commented 9 years ago

hi @wuxianliang,

i think you have an error in your JS code. If you look at the Meteor docs for Meteor.methods you'll see that the arguments are passed individually to your method, not as an array. DDP (and python-meteor) however does use an array.

so the following meteor code:

if (Meteor.isServer) {
  Meteor.methods({
    echo: function(x, y){
      console.log(x);
      console.log(y);
      return [x, y];
    }
  })
}

and the following python code:

#!/usr/bin/env python2

from MeteorClient import MeteorClient

waiting = True
client = MeteorClient('ws://127.0.0.1:3000/websocket', debug=True)
client.connect()

def print_result(err, res):
    global waiting
    print err
    print res
    waiting = False

client.call('echo', ['hello', 'world'], print_result)

while waiting:
    pass

produces the following output on the server:

I20150208-18:15:01.493(0)? 'hello'
I20150208-18:15:01.493(0)? 'world'

and the following output from the python script:

$ ./test.py 
<<<{"msg": "connect", "support": ["pre1"], "version": "pre1"}
>>>{"server_id":"0"}
>>>{"msg":"connected","session":"rdCYW6mfuGMhapxgN"}
<<<{"msg": "method", "params": ["hello", "world"], "id": "1", "method": "echo"}
>>>{"msg":"updated","methods":["1"]}
>>>{"msg":"result","id":"1","result":["hello","world"]}
None
[u'hello', u'world']

The reason you got 'b' with your second bit of code is because you were sending a single argument to the method which was an array. The reason you were getting the exception is probably because the script was ending in while the reply was still being processed (hence the hack in my example to wait for the reply callback before exiting).

I hope that helps!

thanks,

paul.

hharnisc commented 9 years ago

Very thorough answer from @ppettit - it's a good example of not only calling a meteor method, but also how to deal with returning data!

To isolate your question a little further

Let's assume you've got a meteor-python client who is connected to a server

call meteor method from python

client.call('method2Args', ['arg1', 'arg2'])

meteor method

if (Meteor.isServer) {
  Meteor.methods({
    method2Args: function(arg1, arg2){
      console.log(arg1); // logs `arg1` to the server side javascript console
      console.log(arg2); // logs `arg2` to the server side javascript console
      return [arg1, arg2];
    }
  })
}

To summarize, the array of arguments from the python-meteor method call are applied to the meteor method arguments.

I'm going to close this, but please reopen this if you'd like more clarification.

wuxianliang commented 9 years ago

Dear @hharnisc and @ppettit I am sorry for delaying response. Thank you very much! I am working on integration Meteor with OrientDB. Hope I can work out a demo in March.