Make Meteor method synchronous
Asked Answered
E

5

8

I've been attempting to make this function synchronous. I've read several Stack Overflow posts about Async but I'm unable to comprehend how I would be able to make this synchronous. As of now, it is asynchronous therefore it returns undefined before heading into the callback function.

I call it from the client side:

Meteor.call('screenName',function(error,result) {
        if (error) {
          console.log(error);
        }
        else {
          window.alert(result);
        }
      }

And this is the server side method:

Meteor.methods({
  'screenName': function() {
      T.get('search/tweets',
      {
        q:'#UCLA',
        count:1
      },
      function(err,data,response) {
        var temp = data.statuses[0].user.screen_name;
        console.log(temp);
        return temp;
      }
    )
  }
});

I'm using the Twitter API and what I want to do is basically retrieve the screen name from the JSON and return it to a variable on the client side. But this is returning undefined because the callback is being compiled after the compiler has reached the end of the 'screenName' function.

I want it to return the value from the callback function but reading up other examples has not helped me comprehend how I can transform my code. I need to make this function synchronous but I don't know how to do it.

Exploitation answered 28/7, 2015 at 19:24 Comment(4)
Because the twitter package I'm using is Node module and Node runs asynchronously so async helps it run synchronously...here's the link:github.com/meteorhacks/meteor-async Maybe I just understood it wrong. Feel free to correct me.Exploitation
... Wait, have you reposted #31664923?Vicinity
Oh shoot, I didn't realize I asked the same thing. Sorry. Um, how do I close the question? So I don't get banned or something lol..Exploitation
Errr... I think the best thing is to flag as duplicate. But now you have two identical working solutions, one from me and one from @DavidWeldon.Vicinity
V
9

Simply use Meteor.wrapAsync to turn your asynchronous T.get into a synchronously styled one!

It won't actually get executed in a pure "synchronous" way though, it is using a trick known as a Fiber, but you should read the docs to learn more.
Here goes:

var Tget = Meteor.wrapAsync(T.get);

Meteor.methods({
  'screenName': function() {
    return Tget({
      q : '#UCLA',
      count : 1
    }).status[0].user.screen_name;
  }
});
Vicinity answered 28/7, 2015 at 19:50 Comment(1)
Though, I selected this as the correct answer, it still did not work. I started receiving another error and thus, I asked another question that helped to address & solve the initial problem. Here is the link : #31694963Exploitation
R
6

Browser-to-server, it is not possible to call methods synchronously. You're stuck with callback-style code. Synchronous calls are only possible on the server.

http://docs.meteor.com/#/basic/Meteor-call

On the client

Methods called on the client run asynchronously, so you need to pass a callback in order to observe the result of the call. The callback will be called with two arguments, error and result. The error argument will be null unless an exception was thrown. When an exception is thrown, the error argument is a Meteor.Error instance and the result argument is undefined.

On the server

On the server, you don't have to pass a callback — the method call will simply block until the method is complete, returning a result or throwing an exception, just as if you called the function directly.

However, synchronous style code for the server depends if everything else is synchronous. You might want to read the APIs docs if it is possible to write the Twitter API call synchronously. Otherwise, you'll be writing asynchronous code in the end.

Roof answered 28/7, 2015 at 19:35 Comment(3)
Actually I think OP asks about the server-side only (see his code), not about the client-side...Vicinity
@BjornTipling yep, which is why he should consult their documentation :) Additionally, the title is a bit ambiguous provided that he gave client-side code. Meteor method calls can't be synchronous.Roof
Meteor provides built-ins to manage this kind of issue. See my answer.Vicinity
G
1

I use the Promisse, is a great response with async/await.

Example:

// On Client

Template.nameTemplate.onCreated(async function(){
    const callFunctionTest = await getScoreByCountry({ name: 'Testando' });
    console.log(callFunctionTest);

});


async function getScoreByCountry(filter) {
    return await new Promise((resolve, reject) => {
        Meteor.call('app-method-test', filter , (error, resp) => {
            if(error) {
                reject(error)
            } else {
                resolve(resp)
            }
          })
    })
}


// On server

Meteor.methods({
    'app-method-test': test 
});

function test(filter = {}) {
    return App.Collections.NameCollection.findOne(filter)
}
Gomar answered 17/12, 2020 at 20:52 Comment(0)
M
0

@thatgibbyguy answer is the only one that worked for me. I also tried following libraries (maybe they will be useful for somebody):

meteor add simple:reactive-method
meteor add mnmtanish:call
Martial answered 5/2, 2016 at 0:50 Comment(0)
C
-1

This isn't synchronous code, but what I've done to send a server method's result back to a client side function is used serversession to do this. For example:

Meteor.methods({
  'screenName': function() {
      T.get('search/tweets',
      {
        q:'#UCLA',
        count:1
      },
      function(err,data,response) {
        var temp = data.statuses[0].user.screen_name;
        ServerSession.set('screenname',temp)
        return temp;
      }
    )
  }
});

You can now set a reactiveVariable, or a session, or a template helper to be:

ServerSession.get('screenname')
Craquelure answered 28/7, 2015 at 19:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.