Automatic Browser Request Cancellation

Kent C. Dodds
Kent C. Dodds

Take a look at this video transcript where we explore the concept of automatic browser request cancellation. Discover how the browser handles canceled requests and why it's not possible to cancel a request once it's sent to the server. Learn how Remix, a web development tool, simulates browser behavior and handles race conditions and data updates. Find out how to prevent form resubmissions and navigate effectively. Dive into the world of modern web development and understand the intricacies of automatic browser request cancellation.


00:00 Take a look at this. When I hit delete, and I just keep on hitting it, you'll notice that we're getting cancelled requests in here. Right here, the status is cancelled. And then finally, when I stop hitting delete, does a request actually go through and come back and all of that good stuff. What's interesting about this is that the request itself is actually not canceled.

00:19 It's not possible for you to cancel a request. Once the request is out, the server has got it and there's no way for us to communicate, oh wait wait wait, it's kind of like sending an email, oh shoot I forgot to include the, you know, the greeting or whatever, like it's too late, it's already gone And so there's no way for you to say, oh, nevermind, cancel that request. And so it is kind of a bit of a misnomer to call these canceled because they're not actually canceling the request. What they're canceling is the browser's handling of the response. And so, well, every single one of these was saying, hey server, I want you to delete this note, delete the note, delete the note, every single one of these.

00:56 So the server is actually going to be handling each one of those. So if we take a look at our logs here, we're going to get a post for every one of those. The server saw every one of those post requests. So that's just the way that the web works. You send a request, the server's going to get that request.

01:11 If you want to do any sort of actual cancellation, then you need to do that in application code and send an additional request. And that additional request would be, hey, cancel the last one or however you would do that in your own application. So that's an important thing to understand about cancellation. Another thing that's interesting to understand about cancellation is the fact that Remix is actually just simulating what the browser is doing, what the browser would do by default. That's a big part of what Remix is all about, is simulate what the browser does.

01:39 And so here, if I disable JavaScript on the page, then we can actually observe this behavior in the browser in just the way that the browser actually does this. So if I hit the delete button a bunch of times, we're actually getting the same behavior even without any JavaScript. You'll notice the favicon is in a refresh state and every single time I click on it again, it's cancelling. So why does the browser do this? Well the reason the browser does this is because a form submission is a navigation in browser terms.

02:09 Now if you don't have any JavaScript on the page, you submit a form, you are navigating from one place to another even if you end up on the same page. So if we had like a little heart icon right here to favorite this thing, we're not actually navigating anywhere technically, but as far as the browser is concerned, a form submission is a navigation, even if you end up on the same page as where you started off. And so that's an important thing to understand because it means that you cannot, you can't navigate to two places at once. You're going here or you're going here. And so, for the same reason, if I try to click on a link, say I want to go here and oh actually never mind I want to go here, actually never want I want to go here and so navigations whether they be link clicks or form submissions are all going to have the same behavior.

02:56 You can only go to one place and if you decide you don't want to go there anymore we're going to cancel that we're going to go over here but again remember the request was still sent it's just that the browser is like, oh, okay, I'm going to ignore that response and we'll go over here instead. So Remix is doing exactly the same thing. So this has a couple of interesting implications. So, for one, understanding that if the user clicks twice, that actually doesn't really make too much of a difference as far as what the browser is going to do, or Remix in our case, if we've got JavaScript in the client, because Remix is emulating the browser. And so if you want to prevent the user from being able to click twice for some reason, like that actually makes a lot of sense that you might want to prevent the user from clicking twice, then what you could do is, well, First of all, you can't do that without JavaScript in the client.

03:48 You absolutely have to have JavaScript in the client. But what you could do is you could say use navigation. Use navigation right here. And here's our navigation. And then here we could say the button is disabled if navigation.formdata.getIntent is delete.

04:12 So if we're submitting a form with a delete intent that's coming from here, then, oh, okay, this is the navigation that's going on, so I'm gonna disable that button. And so now with that in place, if I come over here and I say delete, then that's gonna be disabled and I'm not gonna be able to click on it again. So that's how you might accomplish that if you really wanted to say, hey whoa, I'm not going to let you do multiple of these at once. You can only do one. And that's just something that is a progressive enhancement piece that you would have to add using JavaScript.

04:44 Because again, cancellation does not mean undo the thing that happened. It just means ignore the response, which is quite beneficial. You're not having to process the JSON response or navigate wherever it says to navigate. So it is useful to have this cancellation mechanism. But yeah, that's something to keep in mind.

05:03 Another thing that the browser is really good at is if you say, hey, I want to navigate here and I want to navigate here instead, oh, I want to navigate here, because it's canceling, it means that we don't have to worry about race conditions of one thing finishing before the next one finishes. And so you never have to worry about ending up in the place you clicked before. So like if the response from this one came back after the response for this one, you're only going to go your ultimate destination, the last thing. It's like, basically the right thing will happen. And Remix emulates this exact same behavior.

05:37 So it handles the race conditions for you. The same thing is true of mutations that happen. So if I mutate this thing and mutate that thing, Remix is going to make sure that race conditions don't make a difference and by the end of it all you have the right data, which is actually another interesting thing. So if I have no JavaScript enabled on the page, what's going on here is I make this mutation and I automatically get all of my data on the page up to date. So this will get deleted, it gets removed from the page, removed from the left nav and all of that stuff.

06:10 And the way that that works is it just says hey do this post and then that post says hey I need you to navigate over to this page, that's going to trigger a full page refresh. We have no JavaScript on the page. And so that brings back all of the HTML, which is generated by the server. And it's going to look in the database and see all of the notes. And that note was deleted.

06:31 So that's how our UI gets updated to reflect the latest version of whatever the data is because the entire HTML document has been regenerated, as it were. When we have JavaScript on the page, Remix emulates the same behavior by automatically revalidating all of the data. And so if I go over here and I say, hey, let's delete this, then it's going to say, okay, let me do that post request. And when that post request is done, it's going to go and revalidate the data that's on the page to make sure that we have the latest and greatest of everything. And that's why when you're using Remix or when you're using the web platform, either way, you never have to actually worry about revalidating or keeping the data up to date.

07:15 There's no code in our application that says, okay, when they delete one of these notes, let's make sure to update this list on the left because that note is no longer there. Remix manages that for us just like the web platform. Remix is just emulating what the web platform does for us automatically. So, you don't have to worry about race conditions, you don't have to worry about race conditions. You don't have to worry about form resubmissions unless you want to like prevent the user from being able to submit the form again, which is a progressive enhancement piece that is pretty straightforward here.

07:46 You don't have to worry about any of the extra different like what if it's in flight and then they navigate over here. No, that request already went and the response is going to be ignored, but the request itself is going to happen one way or another, and Remix is going to manage that for us. So, another example here, I've got JavaScript enabled, so Remix is doing fetch requests, I say, hey, delete this thing, and then I'm going to navigate over here. By the time I end up over there, all of the data has still been updated. Exactly the same as if we had our JavaScript disabled and we're just doing things the way the browser does.

08:24 If I say, hey, delete this thing and then navigate over here, then we're going to end up with the correct data. So thank you Remix for just emulating the way that the platform works. This is how Remix handles form resubmissions, race conditions, form cancellation, navigation cancellation. It's all handled really really well by Remix. So hope that's helpful.

08:46 Ciao.

More Tips