简体   繁体   中英

Make Meteor method synchronous

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.

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;
  }
});

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.

@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

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)
}

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')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM