How to wait for response from the server


#1

I am calling a server method from client using the callback and storing the value for later use. Also i am using okgrow/meteor-persistent-session (https://github.com/okgrow/meteor-persistent-session) for persistent session as shown below.

for(3 times){
Meteor.call(‘format_datetime’, d, function(err, res){
** if(err){ alert(‘Error’);}**
** else{ **
** Session.setPersistent(‘format_datetime_session’, res);**
** var datetimevariable = Session.get(‘format_datetime_session’);**
** console.log(datetimevariable); --> [1]**
** }**
});
var datetimevariable = Session.get(‘format_datetime_session’);
console.log(datetimevariable); --> [2]
//Display the datetimevariable on the client side
//More code
}

The problem is, if i run this code the console.log[2] print 3 times first (because the code inside the for loop of 3) and eventually the same session value is displayed on the client side Ex: 2016-07-31 18:20:00 ; 2016-07-31 18:20:00 ; 2016-07-31 18:20:00 .

Then only the console.log[2] print 3 times. Ex: 2016-07-31 18:20:00 2016-07-31 18:21:00 2016-07-31 18:22:00. This means the original required datetimevariable is not displayed in the client side.

I know this is because client code runs before the server side side operations.But how can i overcome this? If the explanation is confusing I can attach the screenshots. Thanks in advance


#2

I’m assuming this is not simply a requirement to present the results reactively in the UI.

In which case, you need to remove your code at [2] and do the work you would have done there at [1] instead (standard asynchronous coding style).

Alternatively, you could use Promises and async/await if you prefer a more “linear” approach to coding this.

FYI. If you can paste your code between lines of triple backticks it will be easier to read:

```
paste
code
here
```

#3

Thanks @robfallows for your response. Actually I afraid cannot do the way you suggested. Because I am calling more and more server methods later, which i cannot do inside [1]. I could look up on promises and async/await approach. But is there any other approach or solution for my problem. For the clarification I’ve exaplained below. Actually I have all the methods/functions on the client previously. But now i want the methods to be on server.

Meteor.call(some function(){
       var something 1 = Meteor.call(some function1());
       ///some code
       var something 2 = Meteor.call(some function2());
       ///Goes on like this 
});

#4

If you’re doing this on the server you generally don’t need to do anything special. Server-side code in Meteor can be written linearly. The only time that breaks down is when you need to use a third party library not normally used in standard Meteor. Then, you will have to decide between using something like Meteor.wrapAsync or Promises to get linear coding. Also, unless you intend making you methods available to the client (or to other server code acting as a client), there’s no need to use Meteor methods - just use normal functions.


#5

Thank you very much for the information @robfallows. As per your guidance I tried promises using meteor pacakge - deanius:promise. I tried to call the function using promise

var datetimevariable = Meteor.callPromise('format_datetime', d);
console.log(datetimevariable); Prints response as shown below 

I am trying to get the value from the promise as below

datetimevariable.then(function (output){
   console.log(output)
});

Is this the correct way of doing this???


#6

You said you are doing this on the server?

You do not need to do anything special. Instead of

Meteor.call('someMethod1', someParameters1, (error, result1) => {
  Meteor.call('someMethod2', someParameters2, (error, result2) => {
    Meteor.call('someMethod3', someParameters3, (error, result3) => {
    ...
    });
  });
});

just do

result1 = Meteor.call('someMethod1', someParameters1);
result2 = Meteor.call('someMethod2', someParameters2);
result3 = Meteor.call('someMethod3', someParameters3);

#7

Yes. I was trying so. (Note: the code is in client and the method is in server)

var datetimevariable = Meteor.callPromise('format_datetime', d);

But datetimevariable is an object as shown below

My doubt is how to access [[PromiseValue]] !!


#8

No - you don’t need to use Promises with standard Meteor code on the server.

var datetimevariable = Meteor.call('format_datetime', d);

is all you need.


#9

Wait - the call is in the client?

I misunderstood - I thought you were saying the call was in the server too.


#10

Okay @robfallows. Thank you again.


#11

You will need to use a then at the end of your Promise chain. So, in this case (only one Promise):

Meteor.callPromise('format_datetime', d).then(datetimevariable => {
  console.log(datetimevariable);
});

#12

I tried doing so. But the below code which uses the datetimevariable throws the error., because the client code doesn’t wait for the promise reponse

Meteor.callPromise('format_datetime', d).then(datetimevariable => {
  console.log(datetimevariable);
});
//Below code
console.log(datetimevariable); //throws error - ReferenceError: datetimevariable is not defined

#13

That’s correct. Promises don’t solve everything for you. At some point you have to end the Promise chain and (effectively) go back into asynchronous code again - that’s the point of the final then. It’s only inside the body of the then that you will have access to the final result.


#14

What you could do inside that final then is set a reactive variable. As long as your code which needs that value is inside an autorun (and you guard against the initial run where the value isn’t available), you’ll be able to continue processing your data outside of the Promise chain.


#15

Thank you @robfallows.