7

I have the following code inside an Angular application, the html looks like so.

<ng-multiselect-dropdown
    (onSelect)="onSubstringSelect($event)">
</ng-multiselect-dropdown>

That onSubstringSelect is in the .ts part of the component:

onSubstringSelect(item: any) {
    const dataPois = this.getPois(data);
    alert("2nd alert " + dataPois);
    // etc
}

getPois(data): any[] {
    this.api.getPois(data).subscribe((result: any) => {
        alert("1st alert");
        return result.pois;
        }
    }, (error: any) => {
        console.error('error', error);
        return {};
    });

    return null;
}

I was expecing that I had first the alert("1st alert"); and then alert("2nd alert " + dataPois); but that alert is executing first. Why?

3
  • where is onSubstringSelect called? Commented Jun 3, 2019 at 21:54
  • From an Angular component, I will edit the question Commented Jun 3, 2019 at 21:55
  • 1
    It doesn't matter where onSubstringSelect is called. Subscribe is performed asynchronously. Commented Jun 3, 2019 at 21:58

2 Answers 2

1

This is because Rx Streams are asynchronous. When you set up your stream, it does indeed set it up; but nothing runs until there's something listening to this. In the Rx world, this is called subscribing.

When you hand off your stream to the AsyncPipe using stream$ | async; it'll subscribe and all the functions within the setup stream will start functioning in order.

This seems counter intuitive at first, but it actually makes a lot of sense. If you want your console.log to run in the order you want them, add tap() operators in order or redefine your stream to match your expectation.

When you do this:

function A() {
    const stream$ = this.http.get('my-stream-url').pipe(
            tap(() => { console.log('stream is live!') })
        )
    console.log('But this will show up first, because nothing is listening to the stream$ yet!')
    return stream$
}

You can see how the stream will stay stagnant, until someone starts listening to it by subscribing.

Sign up to request clarification or add additional context in comments.

2 Comments

So how can I keep working with my code after getting the data of the ajax call? I don't know how to "wait" for the data comming from the API and then keep doing things in my code
The trick to reactive programming is that you write "all that needs to happen" as a declarative stream. So you either write it as tap() side effects and push the Observable down as far you can before actually subscribing. In the same spirit, it's maybe easier for you to not manually subscribe(), but let Angular take care of it for you. Check out the AsyncPipe examples on angular.io.
1

You do not know when the asynchronous data will be returned. In this case, the answer comes after doing alert("2nd alert " + dataPois);.

4 Comments

is there a way to force the returned data to continue with my code?
I think that alert("2nd alert " + dataPois); return dataPois as undefined
I would try: onSubstringSelect(item: any) { getPois.subscribe( (result: any) => { alert("2nd alert " + dataPois); return result.pois; }, (error: any) => { console.error('error', error); return {}; }); } getPois(data) { return this.api.getPois(data); }
If you want to show dataPois you must run alert("2nd alert " + dataPois); inside subscribe.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.