Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Asynchronous Callbacks #11

Closed
Tolmark12 opened this issue Feb 23, 2015 · 3 comments
Closed

Asynchronous Callbacks #11

Tolmark12 opened this issue Feb 23, 2015 · 3 comments

Comments

@Tolmark12
Copy link

Is there a way to return a result asynchronously like so?

Restivus.addRoute 'people',  authRequired:true,
  post: 
    action: ->
      person = new Person()
      person.save (err, result)->
        if err?
          statusCode: 400
          body: status: "fail", message: "Unable to create person"
        else
          "Person saved!"
@kahmali
Copy link
Owner

kahmali commented Feb 24, 2015

In my understanding, there is nothing inherently in HTTP that will allow an asynchronous response to be made. Once the connection is made during an HTTP request, the only way to respond to that client is within that same HTTP response. The connection is not like a two-way DDP connection (from my currently superficial understanding of DDP). In your example, of course, person would be returned in the response, instead of waiting on the callback. Managing async callbacks seems to be beyond the scope of Restivus and any other REST library that I've researched. For more on asynchronous REST operations, check this out.

Anyhow, I don't think that saving a person is such a long running operation that you actually need an asynchronous response here. I think what you might be looking for is just a way to wait on that callback before returning the endpoint response. For that, you should just be able to use Meteor's wrapAsync() or arunoda's Async.wrap() to wrap that async person.save function to run "synchronously". It will look something like this:

Restivus.addRoute 'people',  authRequired:true,
  post: 
    action: ->
      person = new Person()
      syncSave = Async.wrap person, 'save'
      result = syncSave() 
      "Person saved!"

Without getting into the finer (and quite awesome) details, the result of this is that the previously asynchronous person.save() is now able to be called "synchronously", allowing you to wait on the result of the callback function you would normally pass into person.save() before having to return your endpoint response (as a bonus it does this without blocking the event loop).

The one thing that may not be acceptable about this solution is (again, in my understanding - don't just take my word on this) it does not give you control over the error response. They automatically throw the errors in those wrapped synchronous functions. If they're meteor errors, I think they'll include whatever message is generated in the error; otherwise, I think any other error may just get sent back as a 500 response. In the case of a server error, this is typically acceptable, but that alone may not suffice for your use case. Of course, if some other type of error can be inferred from the result of the wrapped async function, you could have finer control over those responses. I use this pattern when sending notifications to Android devices using GCM, so I know it works if you're okay losing control over the callback errors.

Let me know if that's unclear or just not a satisfactory solution for you.

@Tolmark12
Copy link
Author

This is great, just what I was looking for. I'm hitting one small snag that I'm currently working through (nothing to do with restivus).

Seriously, thanks for the ultra detailed response and explanation, I really appreciate it!

@kahmali
Copy link
Owner

kahmali commented Feb 25, 2015

No problem! Glad I could help. It sounds like you're all set so I'll go ahead and close this. As always, feel free to open another issue if you have any other questions, bugs, or feature requests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants