简体   繁体   中英

right use of Promise in angular

In my web app, I'm trying to make an edit function. For this, I get the edited entity and show a popup form. Currently, I'm struggling to get the entity. I get it, but the edit form is populated only at the second click of the edit button. I think, this is because of some asynchronous operations.

I have a repository class, in which I get the entity with the getSender function:

 export class SenderRepository { sender: Sender; senders: Sender[]; constructor(private http: HttpClient) { this.getSenders(); } getSender(id: number) { this.http.get<Sender>("api/senders/" + id).subscribe(s => this.sender = s); } getSenders() { this.http.get<Sender[]>("api/senders").subscribe(senders => this.senders = senders); } }

Now, I would like to use this entity in the edit form like this (this is the edit click function in the overview component):

 editRow() { new Promise((resolve) => { this.repo.getSender(1); resolve(); }).then(() => { this.sender = this.repo.sender; console.log(this.sender); this.popup.instance.show(); }); }

Because the getSender method is executed asynchronously (right?), I have to wait until I get the result and then use it. But I get in the console at the first time undefined , and only at the second time the entity itself.

Things to note:

  • at first, I'm testing this and therefore I always use the same entity ( this.repo.getSender(1) ), I will replace the index later to a dynamic variable
  • the edit form has an input property of tpye sender , so it shows the values correctly
  • I don't want to use subscribe in my component, it has to be used in the repository

The question is, how can I get this work correctly, that I get the data already after the first click on the edit button?

You do not need to subscribe to the API calls and store data to sender and senders in your Repository (basically a service), unless you are doing some caching. Just let your code elsewhere (consumer) choose when to call your service and fetch data. So just return an Observable from the function.

export class SenderRepository {

  constructor(private http: HttpClient) {
  }

  getSender(id: number) {
    return this.http.get<Sender>("api/senders/" + id);
  }

  getSenders() {
    return this.http.get<Sender[]>("api/senders");
  }
}

Now in your component, call and subscribe to the service to fetch data initially as well as when needed:


import { getSender, getSenders } from './SenderRepository';

// ...

sender: Sender;
senders: Senders[];

constructor(/*private senderService: SenderService*/) { // Could inject as
            // service like this, but here we just import it statically for simplicity
   getSenders().subscribe(senders => this.senders = senders);
}

editRow(id: number) {
   getSender(id).subscribe(sender => {
      this.sender = sender;
      console.log(this.sender);
      this.popup.instance.show();
    });
}

You have moved model from the repo/service to the component, a right step to making your app more Angular.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM