What is the equivalent of "resolve" in ionic?

Hi,

In Angular/Ionic, we could add the resolve into our route to get data before going to another view. How this is done now with Ionic 2?

I would like to make sure some data is ready (http) before to push the new page.

Any idea or suggestion?

Thanks

How about doing the http request and when the response is there move to the next page?

   onClickButton() {
    this.http.get("foo/bar")
      .map(response => response.json())
     .subscribe(response => this.nav.push(FooPage, {bar => response});
  }

You can use the response in the target page using NavParams.

@willb this is a good idea!

What if I want to use a service and then push the page? Something like:

@Page {
  providers: [ItemsService]
}
...
goToNextPage(site) {
  // Get all items
  this.itemsService.retrieveData();

  this.nav.push(NewPage);
}

How would you deal with it?

Your service has to return some promise, observable or invoke a callback. Angular2 is on observables, but I haven’t seen a good example of how to do this particular pattern yet, probably trivial.

A temporary solution/workaround is

itemsService:

 retrieveData(callback) {
  this.http.get("foo/bar")
   .map(response => response.json())
   .subscribe(response => callback(response));
}

Page:

this.itemsService.retrieveData(response => this.nav.push(NewPage));
1 Like

@willb I think I got it. I will try to integrate it within my code. Thanks!

that’s a good idea! I try to prove that can succeed

@willb, what if I need to retrieve couple of information before going to the new page. How you think you will handle it?

Let say, first I need to get items from A with service A, then need to get items from B with service B and finally get items from C with service C.

RxJS? If so, I would need an example. Unless Ionic has a solution for us?

If you use promises is simple, you concatenate .then() calls like this:

serviceA.getData()
  .then((success) => return serviceB.getData())
  .then((success) => return serviceC.getData())
  .then((success) => this.nav.push(NextPage))

As Rxjs observables can act something like promises you need to use .flatMap() or it alias .selectMany() operators, please note i’m new to Rxjs, there could be a better way:

serviceA.getData()
  .flatMap((success) => return serviceB.getData())
  .flatMap((success) => return serviceC.getData())
  .subscribe((success) => this.nav.push(NextPage))

Please note that flatMap operator has to return an observable to be able to chain like this.

@icarus_31 try using async.waterfall(). I’d expect @luchillo17 's approach to call all the then() functions at the same time.

See: http://spion.github.io/promise-nuggets/12-doing-things-in-series.html

Otherwise you can implement something like this:

var datafunctions= [serviceA.getData, serviceB.getData, serviceC.getData];
function getNext() {
   var func = datafunctions.pop();
   func().then(function () {
      if (datafunctions.length > 0) getNext();
   });
}
getNext();

You’re probably better off with waterfall as this ignores errors.
If you can do the services parallel you could try Promise.all(datafunctions).then(function () { console.log(“all done”); });

@willb i’m almost sure the .then() chaining will get the data in serial way as it should wait for the resolve of the service behind it, the observable i’m no so sure as i just looked to the Rxjs docs to make that code.

I have been using Promises for some time and it has worked like that for me, am i wrong?

Ah, looks like you’re right!
It chains nicely:

 function get1() {
    console.log('firing get1')
    return new Promise(function (resolve) {
        setTimeout(resolve, 1000);
    });
}

function get2() {
    console.log('firing get2')
    return new Promise(function (resolve) {
        setTimeout(resolve, 1000);
    });
}

function get3() {
    console.log('firing get3')
    return new Promise(function (resolve) {
        setTimeout(resolve, 1000);
    });
}

get1().then(function () {
    console.log("done with get1");
    return get2();
}).then(function () {
    console.log('done with get2');
    return get3();
}).then(function () {
    console.log('done with get3');
});
1 Like

Actually only the first get1 is the one that needs to be a promise, the other get# functions would be able to just return a value if they didn’t have an async operation, but as timeout is a function itself you did a good use of the promise here.

Btw can you test the Rxjs approach? i’m not so sure of that one, i just looked to the docs, i’m a noob with Rxjs.

He guys, need a crash course for Promises. Any good tutorial to suggest?

Do I need to include (import) a file?

What do I need to add in my service function to return a promise?

Thanks in advance.

Finally, I think I got it by myself. I created promise in my services and it seems to work!

Thanks for your help

I’ve been struggling to solve this problem in Ionic 2 for the last couple of hours. The suggested approach here would work but seems wrong to me. I would expect the components / routes to be self contained and know what they need to do to resolve their data requirements internally, so you can simply navigate to them using a generic function. Then have something like this in the component:

@CanActivate((to: ComponentInstruction, from: ComponentInstruction) => {
    return new Promise((resolve) => {
        // Get data asynchronously, then on success set it and resolve...
        to.routeData.data['key'] = value;
        resolve(true);
    });
})

followed by:

export class SomeComponent {
    something:string;
    constructor(data: RouteData) {
        this.something = data.get('key');
    }
}

I know this should be NavParams in the context of Ionic 2, just outlining how I would expect it to work. Also NavController does have lifecycle hooks, but this won’t solve the problem of resolving data ahead of view switching in an encapsulated way.

1 Like

I am having the same problem. @CanActivitate block doesn’t seem to execute?

Or would I get away with using onPageWillEnter ?
any pointers? thanks.

Any progress on this issue?
For me putting data retreival into the calling view seems very wrong, especially if i need the data in main page…
@CanActivate didn’t worked for me either. since onPageWillEnter doesn’t say its evaluating promises i don’t think its the correct place for retreival of data…

I found this hint: https://webcake.co/page-lifecycle-hooks-in-ionic-2/ he is using

onPageWillEnter() { 
    return this._service.getComments().then(data => this.comments = data);
}

But after a glimpse into ionics view-controller.js:

 ViewController.prototype.willEnter = function () {
        ctrlFn(this, 'onPageWillEnter');
    };

one can see, that the promise which is returned in the example above is not considered, hence we cant be sure that the data is available prior rendering :frowning:
But maybe I’m missing some point here

Posted a summary also on SO, maybe there is someone knowing this issue too:

@brandyshea struggling with this also. Any thoughts on how to approach this scenario?