1

I have a problem that I know is not very challenging. But for some reason, I am having difficulty coming up with a good solution. I need to fetch data from a URL. The URL itself, however, is fetched from another end-point. So, first I fetch an object containing the URL from the server. Upon getting the URL, I access the fetched URL which finally gives me the data I need. The data contains further URLs which I eventually have to fetch. How do I fetch all these data from model hook of ember route?

model(params) {
let futureData = new Ember.RSVP.Promise((resolve,reject) => {
api.ajaxGet(
  `${api.buildV3EnterpriseUrl('reports')}` + '/' + params.report_id
).then(function (successVal) {
  resolve(successVal);
}, function (error) {
  reject(error);

  });
});

futureData.then((success) => {
      return 
       api.xmlRequest('GET',success.aggregationUrls.elements[0].url);
   })

return Ember.RSVP.hash({
  reportData: futureData
});

}
CORS noob
  • 61
  • 5
  • Yes, this is exactly the problem that promises solve. – Bergi May 10 '17 at 19:21
  • Thanks! I understand that promises would solve this? Could you please elaborate a little more? – CORS noob May 10 '17 at 19:27
  • What exactly do you have difficulty with? Please try something and post your attempt, then we can improve that solution if necessary. – Bergi May 10 '17 at 19:31
  • This is what I have. Obviously, does not work. Basically I want the final report data to contain the data fetched from the URL that I fetch from server. – CORS noob May 10 '17 at 19:39
  • You should avoid the [`Promise` constructor antipattern](http://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it) (it should read simply ``let futureData = api.ajaxGet(`${api.buildV3EnterpriseUrl('reports')}` + '/' + params.report_id)``). But I don't see why it would not work. What is the error you are getting? – Bergi May 10 '17 at 19:43

1 Answers1

1

You only forgot one tiny bit:

reportData = futureData.then(…)

Calling then upon the futureData promise doesn't mutate it, it returns a new promise for the result of the callback. You were ignoring that return value.

Then, after also fixing the Promise constructor antipattern, it looks like this:

model(params) {
    const futureData = api.ajaxGet(`${api.buildV3EnterpriseUrl('reports')}/${params.report_id}`);

    const futureReportData = futureData.then(success => {
        return api.xmlRequest('GET',success.aggregationUrls.elements[0].url);
    });

    return Ember.RSVP.hash({
        reportData: futureReportData
    });
}

which could also be shortened to

model(params) {
    return api.ajaxGet(api.buildV3EnterpriseUrl('reports') + '/' + params.report_id)
    .then(success => api.xmlRequest('GET',success.aggregationUrls.elements[0].url))
    .then(reportData => ({reportData}));
}
Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • One more problem :). Now the reportData has an array of URLs. How can I create a promise that waits until all of them resolve and finally return the entire data from the model hook? – CORS noob May 11 '17 at 03:32
  • Basically something like `.then(reportData => Promise.all(reportData.urls.map(ajaxGet)))` – Bergi May 11 '17 at 03:33
  • 1
    That's helpful but I am still having a difficulty? Should I post a new question for this? – CORS noob May 11 '17 at 18:43
  • Yes, please post a new question. – Bergi May 11 '17 at 19:32
  • Thank you for your help! Just posted: http://stackoverflow.com/questions/43924379/complex-ember-promise-chain – CORS noob May 11 '17 at 19:50