-1

I have the following service method:

public getConf() : Promise<string[]> {
let rows : string[] = [];

  this.dao.getData(SearchCriteria.getRecordsFrom("EcegConfig")).then(configs => {
    configs.forEach((cfg : EcegConfRecord) => {
      console.log("START", cfg.data.ecegconf);
      let tmp = cfg.data.ecegconf;
      rows.push(tmp);
    });
  });

return of(rows).toPromise();}

and the following code block in my component in ngOnInit():

 this.http.getConf().then(data => {
  console.log("D A T A", data, data.length, data[0]);
});

I can see the correct strings in data, but length is 0 and data[0] is undefined and I can't use forEach on data. Also the START console.log gives me the correct string items.

(I know its maybe unusual that I used return of(rows).toPromise(), I just started with an Observable output, but that should not be the error or? I'm using this in some other methods and it works as intended there)

As I understood the Promise the .then() waits until the return of the service method is complete, or? so data should have elements within it or? So I have maybe a type error somewhere? (But as I said START delivers a correct string and this is the only thing I'm pushing into rows. so Promise return type should be ok or?

alloisxp
  • 175
  • 3
  • 16
  • Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Liam Oct 02 '19 at 07:54

1 Answers1

0

Let's annotate the code with the time where each line is executed:

public getConf() : Promise<string[]> {
  let rows : string[] = []; // t0

  this.dao.getData(SearchCriteria.getRecordsFrom("EcegConfig")) // t1
    .then(configs => {
      // t10000
      configs.forEach((cfg : EcegConfRecord) => {
        console.log("START", cfg.data.ecegconf);
        let tmp = cfg.data.ecegconf;
        rows.push(tmp);
      });
    });

  return of(rows).toPromise(); // t2
}

The whole point of a promise or observable is to be able to register a callback that will be called asynchronously, when the response of the http request is finally available, at time t10000. But you create an observable which emits your empty array immediately and transform it to a promise. So that can't work.

I would stop using promises and embrace observables, because they're inevitable anyway in Angular, and are more powerful than promises. All you would need if getData returned an observable would be

return this.dao.getData(SearchCriteria.getRecordsFrom("EcegConfig")).pipe(
  map(configs => configs.map((cfg : EcegConfRecord) => cfg.data.ecegconf))
);

If you really want to keep using promises, you can just use

return this.dao.getData(SearchCriteria.getRecordsFrom("EcegConfig")).then(
  configs => configs.map((cfg : EcegConfRecord) => cfg.data.ecegconf)
);
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255