How do I handle really intensive server-side tasks, that can take multiple minutes? It's a user-facing task, so the user can give me some data, and the server will then work in the backend.
I am fairly new to this, but I think my browser won't "wait" for this long, if I am using async/await
? But then if I don't use async await, I won't know whether the task was completed successfully?
Or am I missing something here?
CodePudding user response:
The bigger the task, the more brittle is a solution that depends on a single HTTP request/response. Imagine that the connection breaks after the task has been 99% completed. The client would have to repeat the whole thing.
Instead, I suggest a pattern like the following that depends on several HTTP requests:
- The client (browser) makes a request like
POST /starttask
to start the task and receives a "task ID" in the response. - The task runs on the server while the client can do other things. Any results that the task computes are stored in a database under the task ID.
- The client can check the task progress by making regular requests like
GET /task/<taskID>
and receive a progress notification (50% completed). This can be used to animate a "progress bar" on the UI. - When the task is 100% completed and has yielded a result that the client needs to know, it can retrieve that result with a request like
GET /taskresult/<taskID>
. - If the task result is huge, the client may want to repeat the result retrieval, perhaps with paging (
GET /taskresult/<taskID>?page=1
and so on) until it has received and processed the entire result. This should not burden the server much, because it simply reads the task result from the database. - Finally, the client can delete the task result from the server database with another request like
POST /taskcleanup/<taskID>
.
CodePudding user response:
Using await / async will work as this will wait forever until a promise (request to backend) has been fulfilled. You could show some kind of loading graphic to the user which is how other websites handle lengthy tasks.
Depends how big the task is, but an example if the task is fairly small (eg 10 seconds) we could use a 'loading' state as the way to identify if we should display loading graphic:
function example() {
setLoading(true);
try {
const response = await axios.get('/user?ID=12345');
console.log(response);
} catch (error) {
console.error(error);
} finally {
setLoading(false);
}
}
CodePudding user response:
I think it would be bad to keep the connection open waiting for the response for couple of minutes.
Instead, I would recommend SignalR server side notifications (or equivalent) to notify front end about tasks updates.
Notification DTO would contain all needed information about the task.
Backend:
// Post method
void startTask(params) {
// start backend processing
// after completion notify
signalRHub.notify();
}
On front end you just need subscribe to notifications and add handlers for them.