how do I handle the response order of multiple API calls in React correctly (like auto-complete searching) - reactjs

I'm trying to implement a search box, where every time user types something, the search result will show on the page.
JS fiddle link : https://jsfiddle.net/wsypeter/dh59Lwr2/47/
here is the code for fetching the data and setting the state
basically as I type abc the response might came back in order abc ab a and the result is finally a which is wrong.
How should I fix this ? I know one way is to use debounce, but I think it will still run into issue if the response timeout is super long.
This is an interview question, the interviewer said canceling pending request or debouncing is not the solution he's looking for.
For the above example , there must be 3 requests going out and the final result should be the response of the last request.
How do I do it?

You could use debounce for this kind of issue.
Only after the user finished typing and hasn't typed anything else for e.g. 500ms then you call the api.

Related

#stomp/stompjs latest, subscription() getting in unexpected responses

I am using the latest #stomp/stompjs package in react and it appears to be not working as described so I was wondering if anyone know what was going on.
When I do stompClient.subscribe() I expect only 1 message from the backend. But I normally get an empty object first "{}" and then then the callback goes off again I then get the expect json string. Sometimes I get a 3rd callback with the same json string. I know the page is being redrawn with the new data by react, but I would not think this would cause the callback to go off a second time. Also, this behavior seems to be only for large json string responses. Small response status json objects never returned multiple times in the callback (just the {} object the first time). My workaround was to have a flag that I sett when I do the send command and then is set to false when I get a valid response back. Any extract responses are skipped not saved in the useState hook so react doesn't redraw again.
The second thing I see is sometimes the wrong response is received by the callback. The bookmark paths would be like /location/read and /location/readBL but the response for /location/read would be read by the readBL subscription callback sometimes. This happens 1 out of 10, but I don't understand why it would doing that. The workaround I did is to have the main object key have different words like {camera: {}) and {cameraBL: {}} and see if the object key matches in the expected key in the callback, otherwise skip it.
I assume react is somehow responsible for all this. So, has anyone seen this in their stomp code and know what's going on?
I have inserted flags or filtering to workaround the problem. I have not seen any description of these problems on the web and the stomp home page doesn't talk about any of this.

Should I use POST or GET if I want to send an Array of filters to fetch all articles related with those filters

I havent find ressources online to solve my problem.
I'm creating an app with React Native that fetches and shows news articles from my database.
At the top of the page, there's some buttons with filters inside, for example:
one button "energy",
one button "politics"
one button "people"
one button "china"
etc...
Everytime I press one of those buttons, the filter corresponding is stored in an array "selectedFilters", and I want to fetch my database to only show articles that are corresponding to those filters.
Multiple filters can be selected at the same time.
I know one way of doing it, with a POST request:
await fetch('187.345.32.33:3000/fetch-articles', {
method: 'POST',
headers: {'Content-Type':'application/x-www-form-urlencoded'},
body: 'filters=${JSON.stringify(selectedFilters)}'
});
But the fact is, I read everywhere, and I also was teached, that POST request are used when creating or removing, and theoretically, what I should use is a GET request.
But I don't know how to send an Array with GET request.
I read online that I can pass multiple parameters to my url(for example: arr[0]=selectedFilters[0]&arr[1]=... but the fact is I never know in advance how many items will be in my array.
And also I'm not sure if I could write exactly the same way as my POST request above, but with GET:
await fetch('187.345.32.33:3000/fetch-articles', {
method: 'GET',
headers: {'Content-Type':'application/x-www-form-urlencoded'},
body: 'filters=${JSON.stringify(selectedFilters)}'
});
or if I can only pass items in the url, but does this work ?
await fetch('187.345.32.33:3000/fetch-articles?arr[0]=${selectedFilters[0]', {
Or even better if something like this could work:
await fetch('187.345.32.33:3000/fetch-articles?filters=${JSON.stringify(selectedFilters)}', {
Thanks for your help
You should definitely use a GET request if your purpose is to fetch the data.
One way of passing the array through the URL is by using a map function to create a comma separated string with all the filters. This way you would not need to know in advance how many elements are in the array. The server can then fetch the string from the URL and split it on the commas.
One more method you can try is to save a filters array on the server side for the session. You can then use a POST/PUT request to modify that array with new filter as user adds or remove them. Finally you can use an empty GET request to fetch the news as the server will already have the filters for that session.
But the fact is, I read everywhere, and I also was teached, that POST request are used when creating or removing, and theoretically, what I should use is a GET request.
Yes, you do read that everywhere. It's wrong (or at best incomplete).
POST serves many useful purposes in HTTP, including the general purpose of “this action isn’t worth standardizing.” (Fielding, 2009)
It may help to remember that on the HTML web, POST was the only supported method for requesting changes to resources, and the web was catastrophically successful.
For requests that are effectively read only, we should prefer to use GET, because general purpose HTTP components can leverage the fact that GET is safe (for example, we can automatically retry a safe request if the response is lost on an unreliable network).
I'm not sure if I could write exactly the same way as my POST request above, but with GET
Not quite exactly the same way
A client SHOULD NOT generate content in a GET request unless it is made directly to an origin server that has previously indicated, in or out of band, that such a request has a purpose and will be adequately supported. An origin server SHOULD NOT rely on private agreements to receive content, since participants in HTTP communication are often unaware of intermediaries along the request chain. -- RFC 9110
The right idea is to think about this in the framing of HTML forms; in HTML, the same collection of input controls can be used with both GET and POST. The difference is what the browser does with the information.
Very roughly, a GET form is used when you want to put the key value pairs described by the submitted form into the query part of the request target. So something roughly like
await fetch('187.345.32.33:3000/fetch-articles?filters=${JSON.stringify(selectedFilters)}', {
method: 'GET'
});
Although we would normally want to be using a URI Template to generate the request URI, rather than worrying about escaping everything correctly "by hand".
However, there's no rule that says general purpose HTTP components need to support infinitely long URI (for instance, Internet Explorer used to have a limit just over 2000 characters).
To work around these limits, you might choose to support POST - it's a tradeoff, you lose the benefits of safe semantics and general purpose cache invalidation, you gain that it works in extreme cases.

Saving form data as user types (React/Postgres)

Given a simple textbox to answer a question, how would you go about saving answers as the user types? Assuming that the answer is upserted.
Using a somewhat naive example of an onChange handler and saving answers using an API within that onChange, I ran into two problems:
Sends what seems to be too many patch requests from client to API since it's every time the input textbox answer changes.
If using postgres upsert or creating your own, then the second request made by the onChange handler may not see the first if the user is typing quickly, creating duplicate records for that textbox (two answers for one question)
I need to execute queries beforehand to get necessary relationship values before updating, so the HTTP wait time is fairly long. Fixing this now, but seems to not address the above two issues.
I thought of only saving once the user presses spacebar, but that seems hacky. Normally of course I'd save after clicking a submit button, but in this case it must be as the user types.
Any suggestions / comments? Cheers.
EDIT:
Also tried saving within onBlur.. But this doesn't always get called depending on where the user clicks.
Does it have to patch the data for every keypress or can you use a delay?
For instance...
User starts typing: Register the event, set a timeout for say 3 seconds
If the user keeps typing: reset that timeout back to the full 3s
If the user pauses typing + 3s passes: patch the data with new value
When the user resumes typing: set another timeout

Sending e-mail based on status of previous sub-step

I want to send an email based on status the of a sub-task executed 2 steps before.
In the current action Send an email, I'm using the runAfter event to state the name of the action that failed:
"runAfter": {"HTTP_2": ["Failed"]}
However system does not allow this and I get the following error message.
The action HTTP_2 must belong to the same level as action as Send-an-email.
Any ideas how to get around this?
I believe this error occurs when you are trying to runAfter a step in a different scope. Is the "send_email" step within a condition, scope, or loop? If so the entire condition/scope/loop would need the runAfter (or you would need to have send_email outside of the scope). Other than that it should work. Let me know.
I found a solution which was simple in the end, I just had to switch to 'advanced mode' when entering the condition and enter
#not(equals(outputs('HTTP_2')['statusCode'], 200))
You can thus refer to any step in the workflow.
See attached what the full solution looked like to get a better idea:
enter image description here

REST optimistic-locking and multiple PUTs

Far as I understand, PUT request is not supposed to return any content.
Consider the client wants to run this pseudo code:
x = resource.get({id: 1});
x.field1 = "some update";
resource.put(x);
x.field2 = "another update";
resource.put(x);
(Imagine I have an input control and a button "Save", this allows me to change a part of object "x" shown in an input control, then on button click PUT changes to server, then continue editing and maybe "save" another change to "x")
Following different proposals on how to implement optimistic locking in REST APIs, the above code MUST fail, because version mark (however implemented) for "x" as returned by get() will become stale after put().
Then how do you people usually make it work?
Or do you just re-GET objects after every PUT?
You can use "conditional" actions with HTTP, for example the If-Match header described here:
https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.24
In short: You deliver an ETag with the GET request, and supply this ETag back to the server in the If-Match header. The server will respond with a failure if the resource you are trying to PUT has another ETag. You can also use simple timestamps with the If-Unmodified-Since header.
Of course you will have to make your server code understand conditional requests.
For multiple steps, the PUT can indeed return the new representation, it can therefore include the new ETag or timestamp too. Even if the server does not return the new representation for a PUT, you could still use the timestamp from the response with an If-Unmodified-Since conditional PUT.
Here is probably what I was looking for: https://www.rfc-editor.org/rfc/rfc7231#section-4.3.4
They implicitly say that we CAN return ETag from PUT. Though only in the case server applied the changes as they were given, without any corrections.
However this raises yet another question. In real world app PUT caller will run asynchronously in JS gui, like in my example in the question. So, Save button might be pressed several times with or without entering any changes. If we don't use optimistic locking, then supposed PUT idempotency makes it safe to send another PUT query with each button click, as long as the last one wins (but actually if there were changes then it's not guaranteed, so the question remains).
But with optimistic locking, when first PUT succeeds, it returns updatred ETag, ok? And if there is another PUT request running, still with outdated tag version, that latter request will get 412 and the user will see a message "someone else changed the resource" - but actually it was our former changes.
What do you usually do to prevent that? Disable the Save button until its request is fully completed? What if it times out? Or do you think it's acceptable to see concurrent-change error message if it was a timeout, because the stability is already compromised anyway?

Resources