Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Waiting for a server call to return #426

Open
DirkStevens opened this issue Feb 14, 2014 · 15 comments
Open

Waiting for a server call to return #426

DirkStevens opened this issue Feb 14, 2014 · 15 comments

Comments

@DirkStevens
Copy link

Hey Chris -

At one of our routes we should wait for a server call to return before the route is executed. I wasn't sure how to tackle that? I realize there's a wait method, but what about a "continue" ?

Cheers,

. Dirk

@ryw ryw added the question label Feb 15, 2014
@ryw
Copy link
Contributor

ryw commented Feb 15, 2014

Are you just waiting on a subscription? If so, use waitOn.

Here's an example router configuration from one of my open source projects that shows how waitOn works...

https://github.com/BeDifferential/supporter/blob/master/client/helpers/router.coffee

@ryw ryw self-assigned this Feb 15, 2014
@cmather
Copy link
Contributor

cmather commented Feb 15, 2014

@DirkStevens, What's the use case so I have a better sense of it. @ryw, that will work on the client but I think Dirk is on the server here. Check the methods defined on the lib/server/route_controller but I think you can just call this.options.next(). As far as waiting, I think what you want to do is block the current fiber until you're ready. So to do that you can just grab the current fiber and stop it, or use futures. I'll give a quick example here. More extensive example (video!) on EventedMind (feed archive - fibers and futures). Stay tuned for example...

@cmather
Copy link
Contributor

cmather commented Feb 15, 2014

action: function () {
  var future = new Future;

  // example async
  Meteor.setTimeout(function () {
    // do some stuff
    future.return();
  });

  return future.wait();
}

@DirkStevens
Copy link
Author

@cmather and @ryw - thanks for helping out.

This is a use case on the client side. I could probably use Chris' server example with async.js on the client?

@ryw, your code waits on subscriptions - where I am waiting for a Meteor.call to return.

@tmeasday
Copy link
Contributor

@DirkStevens - you can implement a "psuedo-subscription" from a method call with code something like what I wrote here: #294 (comment)

I think we should "natively" support this in IR somehow.

@vsivsi
Copy link

vsivsi commented Feb 17, 2014

+1 for this. There needs to be an easy way to wait for one or more async callbacks to return.
For example: if you need to load a big JSON file containing the coordinates to be used by d3.js to plot a world map. This is a vanilla async call, having nothing to do with mongo or subscriptions, but is a classic case where showing a "loading" template would be appropriate while waiting.

@ryw ryw added enhancement and removed question labels Feb 17, 2014
@ryw ryw removed their assignment Feb 17, 2014
@cmather
Copy link
Contributor

cmather commented Feb 17, 2014

Maybe we should give thought to a reactive futures library that would work client and server. Is there a standard API out there that is popular?

On Feb 16, 2014, at 4:40 PM, Vaughn Iverson notifications@github.com wrote:

+1 for this. There needs to be an easy way to wait for one or more async callbacks to return.
For example: if you need to JSONP load a big file containing the coordinates to be used by d3.js to plot a world map. This is a vanilla async call, having nothing to do with mongo or subscriptions, but is a classic case where showing a "loading" template would be appropriate while waiting.


Reply to this email directly or view it on GitHub.

@tmeasday
Copy link
Contributor

We’ve used promises (specifically the q library) for this purpose before.

On Monday, 17 February 2014 at 4:15 pm, Chris Mather wrote:

Maybe we should give thought to a reactive futures library that would work client and server. Is there a standard API out there that is popular?

On Feb 16, 2014, at 4:40 PM, Vaughn Iverson <notifications@github.com (mailto:notifications@github.com)> wrote:

+1 for this. There needs to be an easy way to wait for one or more async callbacks to return.
For example: if you need to JSONP load a big file containing the coordinates to be used by d3.js to plot a world map. This is a vanilla async call, having nothing to do with mongo or subscriptions, but is a classic case where showing a "loading" template would be appropriate while waiting.


Reply to this email directly or view it on GitHub.


Reply to this email directly or view it on GitHub (#426 (comment)).

@DirkStevens
Copy link
Author

+1 guys!

@tmeasday will try your sample solution #1 for now

@tmeasday tmeasday added this to the Icebox milestone Mar 17, 2014
@cmather cmather modified the milestones: Requires Triage, Icebox Mar 22, 2014
@tmeasday tmeasday added idea and removed enhancement labels Mar 31, 2014
@cmather cmather modified the milestones: Icebox, Requires Triage May 5, 2014
@ghost
Copy link

ghost commented Jan 31, 2015

i dont know if this is the best solution. But i am doing this to wait on a Meteor.call response

Ready = new Blaze.ReactiveVar(false);
Router.route('feed',{
waitOn: function () {
Meteor.call('getInstagramUserFeed', function(error, result) {
if(!error) {
Ready.set(result)
}
});
return [
function () { return Ready.get(); }
];
},
action: function () {
if (this.ready())
this.render('feed')
else
this.render('LoadingMany');
}
});

what do you think?

@DirkStevens
Copy link
Author

Hey @ivan9074 - looks like a clever solution!

Interested to hear @cmather thoughts on this.

@cmather
Copy link
Contributor

cmather commented Feb 7, 2015

Hi @DirkStevens, As @ivan9074 shows with his example, the wait list can be populated with any function that returns a truthy or falsy value. If the function is reactive, it can reactively trigger a state change in the wait list (true to false or false to true). This affects this.ready() in your route functions. So you can just return a function that returns true or false reactively.

You could also just build your own reactive variable that a helper uses. For example, a helper might render something if the reactive variable is true, otherwise render a loading template.

@Siyfion
Copy link

Siyfion commented Feb 18, 2015

@cmather I have a similar use-case to this; I need to build a complex object when a route is triggered and I do this with a Meteor.call('create-product', function (error, product) {...});. Ideally I then want to pass this product into the data for the route, but I can't seem to figure out a way to stop the route from loading until after the Meteor call is complete... Any ideas?

@outaTiME
Copy link

Here i use same logic from @ivan9074 to wait meteor startup in client side ...

Session.setDefault('location', false);

// took user location data when client starts

if (Meteor.isClient) {
  Meteor.startup(function () {
    var time = Date.now();
    HTTP.call('GET', 'http://www.telize.com/geoip',
      function (error, result) {
        if (!error) {
          var data = result.data;
          console.log('User location took: %s', Date.now() - time);
          Session.set('location', data);
        }
      }
    );
  });
}

Router.configure({
  layoutTemplate: 'layout',
  notFoundTemplate: 'appNotFound',
  loadingTemplate: 'appLoading',
  waitOn: function () {
    return [function () {
      return Session.get('location');
    }];
  }
});

if (Meteor.isClient) {
  Router.onBeforeAction('loading');
}

what do you thing guys, better way ??

@reduxdj
Copy link

reduxdj commented Feb 20, 2016

Wow. this works thanks for this, but this feels so sloppy. Isn't there a better way? a simple promise? I have to tack on these session variables just to set defaultValue in react?

There's got to be a better way

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants