Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I execute a callback on a meteor method that does async calls?

My client is making a call to the server.

Meteor.call('someRequest', params, onAllDoneCallback);

that is processed by (server code)

Meteor.methods({
    'someRequest': function(params, cb) {
        anAsyncFunction(params, cb);
        return true;
    },
});

I'd like the onAllDoneCallback to be triggered on the client side once the anAsyncFunction has finished and triggers its own callback.

However, in Meteor it seems that the second argument of someRequest is ignored and that the onAllDoneCallback is triggered with what someRequest returns, which here is true and which is called before that anAsyncFunction has finished.

In my case I'm more concerned about the timing issue (I'm using it to tell the client that the processing is finished, and not just that the request is well received) but other will probably want to call the callback with arguments from anAsyncFunction

like image 758
Guig Avatar asked Sep 25 '22 13:09

Guig


1 Answers

What you are doing now is passing a function to the server. If that does work, it's very insecure. What you want to do is create a future and then use it to manage the asynchronous function. Here is an example:

let Future = Npm.require('fibers/future');
Meteor.methods({
  someRequest: function (someArg) {
    // for security reasons, make sure you check the type of arguments.
    check(someArg, String);

    // future is an async handler.
    let future = new Future();
    // this is a function for a generic node style callback [ie, function (err, res)]
    let resolver = future.resolver();

    // run your function and pass it the future resolver
    // the future will be resolved when the callback happens.
    anAsyncFunction(someArg, resolver);

    // this meteor method will not end until future has been resolved.
    return future.wait();
  }
});

Alternatively, Meteor provides a wrapAsync that provides similar functionality of wrapping async functions in futures so they can run in meteor methods. That is:

let wrappedAsyncFunction = Meteor.wrapAsync(anAsyncFunction /** second argument is `this` binding*/);
return wrappedAsyncFunction();
like image 186
corvid Avatar answered Sep 29 '22 05:09

corvid