Observables : Cancel previous http request on new subscription call












2















I am working on a search functionality for my project. Once the user types anything on the search bar; on any change in search text I'll be sending the text to backend for validation and receive a response (error or no error in text):



this.searchBar.on('change', () => {

http.post('api_link', {searchText:
this.serachBar.searchText}).subscribe(resp => {
this.resp = resp['Result'];
});
})


Now as the user continuously types in the search bar, multiple validation responses are incoming through back-end. However, on any new change only the latest subscription is valid and any previous call to api is useless.



Is there any way I can cancel the previous subscription on any new call to api using subscribe?



Note: It might seem possible to just wait for all responses but I am also going to display the responses below the search bar(showing a loader till then). So, rather than transition between various response states I want loader to keep loading until the latest response is available.










share|improve this question




















  • 2





    Look into switchMap and debounce.

    – jonrsharpe
    Nov 22 '18 at 13:30











  • you can use unsubscribe() on subscription for every new change. This way old http request will be cancelled and only latest subscription will be valid

    – Yousef khan
    Nov 22 '18 at 13:37











  • a great source that could help you in future : learnrxjs.io

    – Florian
    Nov 22 '18 at 13:47











  • stackoverflow.com/questions/53408051/…

    – martin
    Nov 22 '18 at 14:11
















2















I am working on a search functionality for my project. Once the user types anything on the search bar; on any change in search text I'll be sending the text to backend for validation and receive a response (error or no error in text):



this.searchBar.on('change', () => {

http.post('api_link', {searchText:
this.serachBar.searchText}).subscribe(resp => {
this.resp = resp['Result'];
});
})


Now as the user continuously types in the search bar, multiple validation responses are incoming through back-end. However, on any new change only the latest subscription is valid and any previous call to api is useless.



Is there any way I can cancel the previous subscription on any new call to api using subscribe?



Note: It might seem possible to just wait for all responses but I am also going to display the responses below the search bar(showing a loader till then). So, rather than transition between various response states I want loader to keep loading until the latest response is available.










share|improve this question




















  • 2





    Look into switchMap and debounce.

    – jonrsharpe
    Nov 22 '18 at 13:30











  • you can use unsubscribe() on subscription for every new change. This way old http request will be cancelled and only latest subscription will be valid

    – Yousef khan
    Nov 22 '18 at 13:37











  • a great source that could help you in future : learnrxjs.io

    – Florian
    Nov 22 '18 at 13:47











  • stackoverflow.com/questions/53408051/…

    – martin
    Nov 22 '18 at 14:11














2












2








2


1






I am working on a search functionality for my project. Once the user types anything on the search bar; on any change in search text I'll be sending the text to backend for validation and receive a response (error or no error in text):



this.searchBar.on('change', () => {

http.post('api_link', {searchText:
this.serachBar.searchText}).subscribe(resp => {
this.resp = resp['Result'];
});
})


Now as the user continuously types in the search bar, multiple validation responses are incoming through back-end. However, on any new change only the latest subscription is valid and any previous call to api is useless.



Is there any way I can cancel the previous subscription on any new call to api using subscribe?



Note: It might seem possible to just wait for all responses but I am also going to display the responses below the search bar(showing a loader till then). So, rather than transition between various response states I want loader to keep loading until the latest response is available.










share|improve this question
















I am working on a search functionality for my project. Once the user types anything on the search bar; on any change in search text I'll be sending the text to backend for validation and receive a response (error or no error in text):



this.searchBar.on('change', () => {

http.post('api_link', {searchText:
this.serachBar.searchText}).subscribe(resp => {
this.resp = resp['Result'];
});
})


Now as the user continuously types in the search bar, multiple validation responses are incoming through back-end. However, on any new change only the latest subscription is valid and any previous call to api is useless.



Is there any way I can cancel the previous subscription on any new call to api using subscribe?



Note: It might seem possible to just wait for all responses but I am also going to display the responses below the search bar(showing a loader till then). So, rather than transition between various response states I want loader to keep loading until the latest response is available.







angular rxjs httprequest observable subscribe






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 22 '18 at 13:33









Adrita Sharma

90521329




90521329










asked Nov 22 '18 at 13:30









V SharmaV Sharma

170117




170117








  • 2





    Look into switchMap and debounce.

    – jonrsharpe
    Nov 22 '18 at 13:30











  • you can use unsubscribe() on subscription for every new change. This way old http request will be cancelled and only latest subscription will be valid

    – Yousef khan
    Nov 22 '18 at 13:37











  • a great source that could help you in future : learnrxjs.io

    – Florian
    Nov 22 '18 at 13:47











  • stackoverflow.com/questions/53408051/…

    – martin
    Nov 22 '18 at 14:11














  • 2





    Look into switchMap and debounce.

    – jonrsharpe
    Nov 22 '18 at 13:30











  • you can use unsubscribe() on subscription for every new change. This way old http request will be cancelled and only latest subscription will be valid

    – Yousef khan
    Nov 22 '18 at 13:37











  • a great source that could help you in future : learnrxjs.io

    – Florian
    Nov 22 '18 at 13:47











  • stackoverflow.com/questions/53408051/…

    – martin
    Nov 22 '18 at 14:11








2




2





Look into switchMap and debounce.

– jonrsharpe
Nov 22 '18 at 13:30





Look into switchMap and debounce.

– jonrsharpe
Nov 22 '18 at 13:30













you can use unsubscribe() on subscription for every new change. This way old http request will be cancelled and only latest subscription will be valid

– Yousef khan
Nov 22 '18 at 13:37





you can use unsubscribe() on subscription for every new change. This way old http request will be cancelled and only latest subscription will be valid

– Yousef khan
Nov 22 '18 at 13:37













a great source that could help you in future : learnrxjs.io

– Florian
Nov 22 '18 at 13:47





a great source that could help you in future : learnrxjs.io

– Florian
Nov 22 '18 at 13:47













stackoverflow.com/questions/53408051/…

– martin
Nov 22 '18 at 14:11





stackoverflow.com/questions/53408051/…

– martin
Nov 22 '18 at 14:11












2 Answers
2






active

oldest

votes


















2














I would use a subject to keep everything reactive. in your template html listen to change events and emit a new value to the subject.



 <searchBar (change)="search$.next($event.target.value)" />


then in your component:



  this.subscription = this.search$.pipe(
debounceTime(800),
distinctUntilChanged(),
switchMap(searchText=>http.post('api_link', {searchText})
}).subscribe(response=>{
this.response = response.
});


The switchMap will cancel any HTML request that hasn't completed if a new value is emitted through the subject. you can play with the debouneTime to see what feels right for you. Lastly, make sure you unsubscribe from your subject in the ngOnDestroy, this will prevent any memory links and keep everything nice and perfromant.:



ngOnDestroy(){
this.subscription. unsubscribe();
}


Suresh's answer has a distinctUntilChanged() which is an excellent addition to the solution. I'm adding it but want to give credit to his answer below. This is a benefit because if I search for egg the request is made. but then I add a s the end of egg and change my mind before the debounce is completed another duplicate HTTP post with a search of egg will not be made.






share|improve this answer


























  • Thanks a lot for such detailed solution.

    – V Sharma
    Nov 25 '18 at 14:16











  • Actually my element is dynamically created in typescript, so i can't add change event listener in template. Whats the way to do this in ts only? (as mentioned in the question i have a change event listener in ts for this)

    – V Sharma
    Nov 30 '18 at 23:12











  • @VSharma this is probably out of the scope of the original question. However, how are you creating the element dynamically?

    – JoshSommer
    Dec 1 '18 at 19:56











  • if you have the search bar class in your code you can subscribe to the change event emitter directly. so: this.searchBar.change.pipe( instead of this.search$.pipe( this is because Angular's Event Emitter extends RxJS's Subject. I thought I read at one time the Angular team didn't recommend subscribing to Event Emitters directly. But I could be mistaken, you may want to some digging around to confirm this. This isn't a situation I've typically encountered so I haven't had to worry about it.

    – JoshSommer
    Dec 1 '18 at 20:10





















0














You need to use debounceTime and switchMap operator.



this.searchBar.on('change', () => {

of(this.serachBar.searchText).pipe(
debounceTime(400),
distinctUntilChanged(),
switchMap((text)=> {
return http.post('api_link', {searchText: text}).map(resp => {
return resp['Result'];
});
});
).subscribe(response=> console.log(response));

});





share|improve this answer
























  • I have few doubts.What does of(this.serachBar.searchText) do? Is it just to create an initial observable? And what is the text parameter in switchMap?

    – V Sharma
    Nov 30 '18 at 20:07













  • Aren't we using 2 observables here? from of and http.post

    – V Sharma
    Nov 30 '18 at 22:23











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53432096%2fobservables-cancel-previous-http-request-on-new-subscription-call%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









2














I would use a subject to keep everything reactive. in your template html listen to change events and emit a new value to the subject.



 <searchBar (change)="search$.next($event.target.value)" />


then in your component:



  this.subscription = this.search$.pipe(
debounceTime(800),
distinctUntilChanged(),
switchMap(searchText=>http.post('api_link', {searchText})
}).subscribe(response=>{
this.response = response.
});


The switchMap will cancel any HTML request that hasn't completed if a new value is emitted through the subject. you can play with the debouneTime to see what feels right for you. Lastly, make sure you unsubscribe from your subject in the ngOnDestroy, this will prevent any memory links and keep everything nice and perfromant.:



ngOnDestroy(){
this.subscription. unsubscribe();
}


Suresh's answer has a distinctUntilChanged() which is an excellent addition to the solution. I'm adding it but want to give credit to his answer below. This is a benefit because if I search for egg the request is made. but then I add a s the end of egg and change my mind before the debounce is completed another duplicate HTTP post with a search of egg will not be made.






share|improve this answer


























  • Thanks a lot for such detailed solution.

    – V Sharma
    Nov 25 '18 at 14:16











  • Actually my element is dynamically created in typescript, so i can't add change event listener in template. Whats the way to do this in ts only? (as mentioned in the question i have a change event listener in ts for this)

    – V Sharma
    Nov 30 '18 at 23:12











  • @VSharma this is probably out of the scope of the original question. However, how are you creating the element dynamically?

    – JoshSommer
    Dec 1 '18 at 19:56











  • if you have the search bar class in your code you can subscribe to the change event emitter directly. so: this.searchBar.change.pipe( instead of this.search$.pipe( this is because Angular's Event Emitter extends RxJS's Subject. I thought I read at one time the Angular team didn't recommend subscribing to Event Emitters directly. But I could be mistaken, you may want to some digging around to confirm this. This isn't a situation I've typically encountered so I haven't had to worry about it.

    – JoshSommer
    Dec 1 '18 at 20:10


















2














I would use a subject to keep everything reactive. in your template html listen to change events and emit a new value to the subject.



 <searchBar (change)="search$.next($event.target.value)" />


then in your component:



  this.subscription = this.search$.pipe(
debounceTime(800),
distinctUntilChanged(),
switchMap(searchText=>http.post('api_link', {searchText})
}).subscribe(response=>{
this.response = response.
});


The switchMap will cancel any HTML request that hasn't completed if a new value is emitted through the subject. you can play with the debouneTime to see what feels right for you. Lastly, make sure you unsubscribe from your subject in the ngOnDestroy, this will prevent any memory links and keep everything nice and perfromant.:



ngOnDestroy(){
this.subscription. unsubscribe();
}


Suresh's answer has a distinctUntilChanged() which is an excellent addition to the solution. I'm adding it but want to give credit to his answer below. This is a benefit because if I search for egg the request is made. but then I add a s the end of egg and change my mind before the debounce is completed another duplicate HTTP post with a search of egg will not be made.






share|improve this answer


























  • Thanks a lot for such detailed solution.

    – V Sharma
    Nov 25 '18 at 14:16











  • Actually my element is dynamically created in typescript, so i can't add change event listener in template. Whats the way to do this in ts only? (as mentioned in the question i have a change event listener in ts for this)

    – V Sharma
    Nov 30 '18 at 23:12











  • @VSharma this is probably out of the scope of the original question. However, how are you creating the element dynamically?

    – JoshSommer
    Dec 1 '18 at 19:56











  • if you have the search bar class in your code you can subscribe to the change event emitter directly. so: this.searchBar.change.pipe( instead of this.search$.pipe( this is because Angular's Event Emitter extends RxJS's Subject. I thought I read at one time the Angular team didn't recommend subscribing to Event Emitters directly. But I could be mistaken, you may want to some digging around to confirm this. This isn't a situation I've typically encountered so I haven't had to worry about it.

    – JoshSommer
    Dec 1 '18 at 20:10
















2












2








2







I would use a subject to keep everything reactive. in your template html listen to change events and emit a new value to the subject.



 <searchBar (change)="search$.next($event.target.value)" />


then in your component:



  this.subscription = this.search$.pipe(
debounceTime(800),
distinctUntilChanged(),
switchMap(searchText=>http.post('api_link', {searchText})
}).subscribe(response=>{
this.response = response.
});


The switchMap will cancel any HTML request that hasn't completed if a new value is emitted through the subject. you can play with the debouneTime to see what feels right for you. Lastly, make sure you unsubscribe from your subject in the ngOnDestroy, this will prevent any memory links and keep everything nice and perfromant.:



ngOnDestroy(){
this.subscription. unsubscribe();
}


Suresh's answer has a distinctUntilChanged() which is an excellent addition to the solution. I'm adding it but want to give credit to his answer below. This is a benefit because if I search for egg the request is made. but then I add a s the end of egg and change my mind before the debounce is completed another duplicate HTTP post with a search of egg will not be made.






share|improve this answer















I would use a subject to keep everything reactive. in your template html listen to change events and emit a new value to the subject.



 <searchBar (change)="search$.next($event.target.value)" />


then in your component:



  this.subscription = this.search$.pipe(
debounceTime(800),
distinctUntilChanged(),
switchMap(searchText=>http.post('api_link', {searchText})
}).subscribe(response=>{
this.response = response.
});


The switchMap will cancel any HTML request that hasn't completed if a new value is emitted through the subject. you can play with the debouneTime to see what feels right for you. Lastly, make sure you unsubscribe from your subject in the ngOnDestroy, this will prevent any memory links and keep everything nice and perfromant.:



ngOnDestroy(){
this.subscription. unsubscribe();
}


Suresh's answer has a distinctUntilChanged() which is an excellent addition to the solution. I'm adding it but want to give credit to his answer below. This is a benefit because if I search for egg the request is made. but then I add a s the end of egg and change my mind before the debounce is completed another duplicate HTTP post with a search of egg will not be made.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 22 '18 at 14:04

























answered Nov 22 '18 at 13:49









JoshSommerJoshSommer

1,370814




1,370814













  • Thanks a lot for such detailed solution.

    – V Sharma
    Nov 25 '18 at 14:16











  • Actually my element is dynamically created in typescript, so i can't add change event listener in template. Whats the way to do this in ts only? (as mentioned in the question i have a change event listener in ts for this)

    – V Sharma
    Nov 30 '18 at 23:12











  • @VSharma this is probably out of the scope of the original question. However, how are you creating the element dynamically?

    – JoshSommer
    Dec 1 '18 at 19:56











  • if you have the search bar class in your code you can subscribe to the change event emitter directly. so: this.searchBar.change.pipe( instead of this.search$.pipe( this is because Angular's Event Emitter extends RxJS's Subject. I thought I read at one time the Angular team didn't recommend subscribing to Event Emitters directly. But I could be mistaken, you may want to some digging around to confirm this. This isn't a situation I've typically encountered so I haven't had to worry about it.

    – JoshSommer
    Dec 1 '18 at 20:10





















  • Thanks a lot for such detailed solution.

    – V Sharma
    Nov 25 '18 at 14:16











  • Actually my element is dynamically created in typescript, so i can't add change event listener in template. Whats the way to do this in ts only? (as mentioned in the question i have a change event listener in ts for this)

    – V Sharma
    Nov 30 '18 at 23:12











  • @VSharma this is probably out of the scope of the original question. However, how are you creating the element dynamically?

    – JoshSommer
    Dec 1 '18 at 19:56











  • if you have the search bar class in your code you can subscribe to the change event emitter directly. so: this.searchBar.change.pipe( instead of this.search$.pipe( this is because Angular's Event Emitter extends RxJS's Subject. I thought I read at one time the Angular team didn't recommend subscribing to Event Emitters directly. But I could be mistaken, you may want to some digging around to confirm this. This isn't a situation I've typically encountered so I haven't had to worry about it.

    – JoshSommer
    Dec 1 '18 at 20:10



















Thanks a lot for such detailed solution.

– V Sharma
Nov 25 '18 at 14:16





Thanks a lot for such detailed solution.

– V Sharma
Nov 25 '18 at 14:16













Actually my element is dynamically created in typescript, so i can't add change event listener in template. Whats the way to do this in ts only? (as mentioned in the question i have a change event listener in ts for this)

– V Sharma
Nov 30 '18 at 23:12





Actually my element is dynamically created in typescript, so i can't add change event listener in template. Whats the way to do this in ts only? (as mentioned in the question i have a change event listener in ts for this)

– V Sharma
Nov 30 '18 at 23:12













@VSharma this is probably out of the scope of the original question. However, how are you creating the element dynamically?

– JoshSommer
Dec 1 '18 at 19:56





@VSharma this is probably out of the scope of the original question. However, how are you creating the element dynamically?

– JoshSommer
Dec 1 '18 at 19:56













if you have the search bar class in your code you can subscribe to the change event emitter directly. so: this.searchBar.change.pipe( instead of this.search$.pipe( this is because Angular's Event Emitter extends RxJS's Subject. I thought I read at one time the Angular team didn't recommend subscribing to Event Emitters directly. But I could be mistaken, you may want to some digging around to confirm this. This isn't a situation I've typically encountered so I haven't had to worry about it.

– JoshSommer
Dec 1 '18 at 20:10







if you have the search bar class in your code you can subscribe to the change event emitter directly. so: this.searchBar.change.pipe( instead of this.search$.pipe( this is because Angular's Event Emitter extends RxJS's Subject. I thought I read at one time the Angular team didn't recommend subscribing to Event Emitters directly. But I could be mistaken, you may want to some digging around to confirm this. This isn't a situation I've typically encountered so I haven't had to worry about it.

– JoshSommer
Dec 1 '18 at 20:10















0














You need to use debounceTime and switchMap operator.



this.searchBar.on('change', () => {

of(this.serachBar.searchText).pipe(
debounceTime(400),
distinctUntilChanged(),
switchMap((text)=> {
return http.post('api_link', {searchText: text}).map(resp => {
return resp['Result'];
});
});
).subscribe(response=> console.log(response));

});





share|improve this answer
























  • I have few doubts.What does of(this.serachBar.searchText) do? Is it just to create an initial observable? And what is the text parameter in switchMap?

    – V Sharma
    Nov 30 '18 at 20:07













  • Aren't we using 2 observables here? from of and http.post

    – V Sharma
    Nov 30 '18 at 22:23
















0














You need to use debounceTime and switchMap operator.



this.searchBar.on('change', () => {

of(this.serachBar.searchText).pipe(
debounceTime(400),
distinctUntilChanged(),
switchMap((text)=> {
return http.post('api_link', {searchText: text}).map(resp => {
return resp['Result'];
});
});
).subscribe(response=> console.log(response));

});





share|improve this answer
























  • I have few doubts.What does of(this.serachBar.searchText) do? Is it just to create an initial observable? And what is the text parameter in switchMap?

    – V Sharma
    Nov 30 '18 at 20:07













  • Aren't we using 2 observables here? from of and http.post

    – V Sharma
    Nov 30 '18 at 22:23














0












0








0







You need to use debounceTime and switchMap operator.



this.searchBar.on('change', () => {

of(this.serachBar.searchText).pipe(
debounceTime(400),
distinctUntilChanged(),
switchMap((text)=> {
return http.post('api_link', {searchText: text}).map(resp => {
return resp['Result'];
});
});
).subscribe(response=> console.log(response));

});





share|improve this answer













You need to use debounceTime and switchMap operator.



this.searchBar.on('change', () => {

of(this.serachBar.searchText).pipe(
debounceTime(400),
distinctUntilChanged(),
switchMap((text)=> {
return http.post('api_link', {searchText: text}).map(resp => {
return resp['Result'];
});
});
).subscribe(response=> console.log(response));

});






share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 22 '18 at 13:44









Suresh Kumar AriyaSuresh Kumar Ariya

4,7761215




4,7761215













  • I have few doubts.What does of(this.serachBar.searchText) do? Is it just to create an initial observable? And what is the text parameter in switchMap?

    – V Sharma
    Nov 30 '18 at 20:07













  • Aren't we using 2 observables here? from of and http.post

    – V Sharma
    Nov 30 '18 at 22:23



















  • I have few doubts.What does of(this.serachBar.searchText) do? Is it just to create an initial observable? And what is the text parameter in switchMap?

    – V Sharma
    Nov 30 '18 at 20:07













  • Aren't we using 2 observables here? from of and http.post

    – V Sharma
    Nov 30 '18 at 22:23

















I have few doubts.What does of(this.serachBar.searchText) do? Is it just to create an initial observable? And what is the text parameter in switchMap?

– V Sharma
Nov 30 '18 at 20:07







I have few doubts.What does of(this.serachBar.searchText) do? Is it just to create an initial observable? And what is the text parameter in switchMap?

– V Sharma
Nov 30 '18 at 20:07















Aren't we using 2 observables here? from of and http.post

– V Sharma
Nov 30 '18 at 22:23





Aren't we using 2 observables here? from of and http.post

– V Sharma
Nov 30 '18 at 22:23


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53432096%2fobservables-cancel-previous-http-request-on-new-subscription-call%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

"Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

Alcedinidae

RAC Tourist Trophy