Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there a way to abort a search request? #161

Closed
romaincointepas opened this issue Nov 3, 2015 · 23 comments
Closed

Is there a way to abort a search request? #161

romaincointepas opened this issue Nov 3, 2015 · 23 comments

Comments

@romaincointepas
Copy link

Useful when connectivity is bad and search results don't come back nearly instantly.

User search for something, we call index.search(), then the user do something that would make the search results obsolete (navigates away?). In this case it would be good to have a way to abort the current request (and index.search callback would either never be called or be called with an error).

@vvo
Copy link

vvo commented Nov 3, 2015

What we could provide is a client.abortPendingRequests(). So that you could call this in the situations you are facing.

If this is a real use case I would be happy to provide it to you.

This would only solve the "I want to abort all pending requests because I do not care anymore about the results" issue.

@romaincointepas
Copy link
Author

That would be awesome, as I think it is cleaner than letting the request runs and ignoring the results when they come back.

Also I am wondering, let's say I call index.search twice, what happens to the first request if it didn't return when I call index.search the second time? Is it cancelled? (that would happens a lot with a search showing instant results).

@vvo
Copy link

vvo commented Nov 3, 2015

I think it is cleaner than letting the request runs and ignoring the results when they come back

Yes

Is it cancelled?

So no it's not because from the POV of an API client we try to be close to a simple request/response library.

Handling outdated answers is the goal of our https://github.com/algolia/algoliasearch-helper-js that you should use if you are building an instant search result page.

But even that, right now the helper is not actively cancelling the requests. Maybe we should. As I am not sure, I need the helper from the helper creator.

@bobylito I cannot exactly recall when do we discard response in the helper. Can you write it down here (and then we add it to the helper doc).

@mspivak
Copy link

mspivak commented Feb 4, 2016

+1. Are there any news on this subject? Is there a way to do it using the helper? I couldn't found it in the docs.

My particular real use case: I've got a search box on the navbar that uses Algolia for suggestions. However, if the user hits enter before the Algolia request finishes I want to abort the Algolia request and redirect him to a results page.

@vvo
Copy link

vvo commented Mar 10, 2016

This will go in V4 #195

@vvo vvo closed this as completed Mar 10, 2016
@mspivak
Copy link

mspivak commented Mar 12, 2016

Nice!

El Thursday, March 10, 2016, Vincent Voyer [email protected]
escribió:

This will go in V4 #195
#195


Reply to this email directly or view it on GitHub
#161 (comment)
.

Mauro

@ilonashub
Copy link

Hey, Is there any progress with that?
Thanks :)

@Haroenv
Copy link
Contributor

Haroenv commented Sep 28, 2017

Some context on why this issue didn't move in the last year: we rescheduled our plans of releasing a v4 until this year, which caused this issue to slip through the holes in the net.

However canceling requests isn't part of the responsibilities of the API client by default, because overall in most implementations of http requests, it isn't feasible to actually cancel a request, you can simply ignore the result in most cases.

What use case were you thinking of that this would be useful? Some more context would be great for us to see how to handle it.

We are also following the spec work on cancelable promises, but tc39 decided that that isn't how they want to solve it. In Fetch a solution has been found, which is to do with a controller for the actual request. I can see us implementing a similar solution if it makes sense in the use cases where the result can't simply be ignored

@vvo
Copy link

vvo commented Sep 28, 2017

@ilonashub Can you provide us more details about how you would use a cancel() method? What is your use case for the need of having a cancel method/feature? Thanks

@mspivak
Copy link

mspivak commented Sep 28, 2017 via email

@Haroenv
Copy link
Contributor

Haroenv commented Sep 29, 2017

I think the problem here is even if we provided a way to "cancel" a search request, the connection can't be severed, and so those real issues on connection limit would not be solved. Both XHR and Fetch don't provide a way to close the connection. This does make sense on node though, I think there's a way to completely cancel a request there.

In real usage (we always do per-keystroke queries) we don't see the case where older requests mess up the interface because newer requests can't be done, so it's not a huge priority, but it would still be nice.

I think something we can wait for, is an implementation of FetchController in a mainstream browser, and see how we can work with that. Our requests now are happening with XHR though, but that would prove its worth on doing the conversion.

See also https://developers.google.com/web/updates/2017/09/abortable-fetch

@adylevy
Copy link

adylevy commented Nov 26, 2017

@vvo +1 for .cancel method.

use case:
in an autocomplete field, when using algolia via the JS api I'd like to cancel old calls to reduce load on the client side when I know the app won't use any of the 'old' data.

make sense?

@bobylito
Copy link

bobylito commented Nov 26, 2017

in an autocomplete field, when using algolia via the JS api I'd like to cancel old calls to reduce load on the client side when I know the app won't use any of the 'old' data.

I'm no network expert so what I'm saying might just be plain wrong :) However, it is my understanding that when a request is sent to Algolia, cancelling it on the JS side won't have any impact either on Algolia or the network overall.

That being said, the problem that you mention is that on the client side we want to be sure that any result displayed is not outdated and we want as much as much as possible them to be in sync with what the user has typed, right?

And the JS Helper has a few elements to help you on that (even though its integration is not straightforward in autocomplete.js). The JS Helper keeps track of the order of the requests and drops the one that are outdated / in the wrong order. It also provides information about the state of the search queue.

@vvo
Copy link

vvo commented Nov 27, 2017

@adylevy Along with @bobylito comment one thing that could help us understand what you want is you to create a simple online example and then give us steps to reproduce a bad behavior.

Example:

  • go to url
  • open network tab
  • set connection to ..
  • type "ab"..
  • see requests
  • Feature request: if I had a cancel method, the behaviour would be... And it would be better because..

Thanks a lot

@nunomaduro
Copy link

Closing this issue because it's inactive, already solved, old or not relevant anymore. Feel free to reply if you're still experiencing this issue.

@skipjack
Copy link

I think the problem here is even if we provided a way to "cancel" a search request, the connection can't be severed, and so those real issues on connection limit would not be solved. Both XHR and Fetch don't provide a way to close the connection. This does make sense on node though, I think there's a way to completely cancel a request there.

Now that AbortController is a thing, would you consider re-opening this?

In real usage (we always do per-keystroke queries) we don't see the case where older requests mess up the interface because newer requests can't be done, so it's not a huge priority, but it would still be nice.

@Haroenv why is it that "newer requests can't be done"? If you're using the client directly I'm pretty sure the case exists where a previous query can return after a newer query (which introduces the scenario where older results might be saved over the desired ones).

@Haroenv
Copy link
Contributor

Haroenv commented Mar 29, 2020

"newer queries can't be done" is in context of people using InstantSearch or the JavaScript Helper, which takes this in account.

The reason we are hesitant about this, is because the network request will always still go to the server, it's just that the response will be ignored by browsers (even with AbortController, although note that we are using XHR, not fetch, for better support of older browsers, and environments like React Native). This means that it will still count to your Algolia quota. Since the query is done, we don't see a reason why you can't at least have that response in the cache, so it doesn't need to be done again next time.

What reason are you looking for an abort method @skipjack?

@skipjack
Copy link

skipjack commented Mar 31, 2020

"newer queries can't be done" is in context of people using InstantSearch or the JavaScript Helper, which takes this in account.

Makes sense but I'm using this api client directly, not InstantSearch. What's the "JavaScript Helper"?

The reason we are hesitant about this, is because the network request will always still go to the server, it's just that the response will be ignored by browsers [...] we don't see a reason why you can't at least have that response in the cache, so it doesn't need to be done again next time.

Understood though I'm pretty sure XHR responses are not cached by default in most browsers (at least not in the latest version of Chrome). Are you referring to some server-side caching that Algolia does or are you assuming most folks are using ServiceWorkers and caching stuff client-side?

What reason are you looking for an abort method @skipjack?

When using this client directly, it's possible to make an initial call that resolves after a later call (not specific to this package, the scenario occurs with any use of fetch / xhr though it presents itself more with slower services). In this case, if you don't abort or otherwise ignore the initial promise then you can end up showing outdated results.

When using fetch directly, I would just abort these calls and then somehow handle the abort error. So I'm just looking for the best alternative to that within the context of this client.

@Haroenv
Copy link
Contributor

Haroenv commented Mar 31, 2020

code in the helper is this: (slightly internal with the concept of tagging the queries, but you can do the same on your end)

https://github.com/algolia/algoliasearch-helper-js/blob/e98d90cc6b8913f65f4b28f1fe57174b06c7a150/src/algoliasearch.helper.js#L1250-L1253

If you are using v4, you can make a custom requester using fetch and handling the failure yourself as a non-retryable failure, if this is the method you prefer using

@skipjack
Copy link

Interesting, I didn't even realize the helper existed. Thanks for your quick responses, I understand why you don't want to pursue a .cancel or .abort method here now.

@KeerthanaManoharan
Copy link

@vvo +1 for .cancel method.

use case:
in an autocomplete field, when using algolia via the JS api I'd like to cancel old calls to reduce load on the client side when I know the app won't use any of the 'old' data.

make sense?

Im also having the same problem with this use case in fetch call can anyone help me to abort the API call of previous text and to request only the input given by the user now

For example :
search text is agile
when user types a and g
cancel the request for 'a' and fire the request for ag

@vvo
Copy link

vvo commented Jul 17, 2020

@KeerthanaManoharan I guess you could use the v4 of the client, create your own requester as shown here:

And use fetch (https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) instead of XHR, plus an abort controller: https://developer.mozilla.org/en-US/docs/Web/API/AbortController#Examples

Then when using the client, when you receive user input, if there's a request going on, you could abort it. That's some good work to do but doable. Maybe it will be inside Algolia at some point (I have no idea what I am talking about :D).

But again, you could also just do what the JavaScript helper does: instead of aborting you just discard old requests. To do so, when receiving responses from Algolia, you compare the response query to the user query, if they do not match then your discard the response because it's outdated.

@Haroenv
Copy link
Contributor

Haroenv commented Jul 17, 2020

Our official stance is still the following:

  1. canceling a search request does not free up significant resources
  2. the request has still happened, meaning it's still counted in your operations
  3. we see people using backspace fairly frequently, which would need to be requested again, even if it has already happened

Therefore we see the most efficient way to deal with stale requests to be to cached, but only display the result of the current search query.

If you really want to cancel a request, you could write your custom requester (with fetch), and accept an AbortController yourself, however, you'll need to also change the implementation of transporter (see createMappedRequestOptions & retryableRequest) to accept that argument and forward it to fetch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants