tmeasday / meteor-router

MIT License
366 stars 76 forks source link

Waiting for callback #132

Closed bernatfortet closed 11 years ago

bernatfortet commented 11 years ago

I am trying to create an endpoint inside my meteor API to use an NPM library that requests information from an API. Ideally I would like to be able to do the following

Meteor.Router.add(
    "/request/:id.json", ( requestId ) ->
        someLibrary.request( 'someUrl', ( err, data ) ->
                return data
        )

Clearly... this is not possible as Meteor doesn't wait for the callback

I have tried the following without much success:

Meteor.Router.add(
    "/request/:id.json", ( requestId ) ->
        future = new Future();
        Meteor.setTimeout( =>
            return future["this is not printend in the window"]
        , 1000)
                return future.wait();
)

In this case, the future['content'] is not printend as a response.

I have been trying other options without luck. Any idea on how to do this?

Thanks!

tmeasday commented 11 years ago

Hi, you'll need to call future.return(...) to get the data out to the the future.wait().

Apart from that I think you are on the right track.

bernatfortet commented 10 years ago

@tmeasday future.return(...) works. But I cannot return an object var response = {} The error is: TypeError: first argument must be a string or Buffer

Any idea? Thanks for your help!

tmeasday commented 10 years ago

From memory, you have to return a string or an array in a server route https://github.com/tmeasday/meteor-router#server-side-routing

bernatfortet commented 10 years ago

This is the exact code I am using

Meteor.Router.add(
    "/api/v1/cards/:id.json", ( cardId ) ->

        future = new Future();
        card = {}

        Meteor.setTimeout( =>
            console.log card
            return future.return( card )
        , 1000)

        return future.wait();
        tutor.card( cardId, ( err, respone ) =>
            card = respone
        )
)

Card is return as a JSON object

tmeasday commented 10 years ago

Yes but what do you actually want to return? Maybe EJSON.serialize(card) ? Remember this is a http response, no such thing as objects.

bernatfortet commented 10 years ago

It's working for me now: with EJSON.stringify

Nonetheless, it's not really good, since the request might take too long and miss the timeout. Is there any better way to do this, and be efficient with respone timing?

Thanks!

here is the working code, just in case somebody needs it.

Meteor.Router.add(
    "/api/v1/cards/:id.json", ( cardId ) ->

        future = new Future();
        card = {}

        tutor.card( +cardId, ( err, respone ) =>
            console.log respone
            card = respone
        )

        Meteor.setTimeout( =>
            console.log card
            return future.return( EJSON.stringify(card) )
        , 2000)

        return future.wait();

)
tmeasday commented 10 years ago

Just do the future.return() in the callback for tutor.card()

bernatfortet commented 10 years ago

Got it!

It works like a charm!

Here is the code just in case somebody needs it.

Meteor.Router.add(
    "/api/v1/cards/:id.json", ( cardId ) ->
        future = new Future();
        tutor.card( +cardId, ( err, card ) =>
            future.return( EJSON.stringify(card) )
        )
        return future.wait();
)

Thanks @tmeasday !