Check out a free preview of the full Interviewing for Front-End Engineers course
The "Timing: Debounce Solution" Lesson is part of the full, Interviewing for Front-End Engineers course featured in this preview video. Here's what you'd learn in this lesson:
Jem live codes the solution to the Debounce exercise. Jem also brings up how you could also use throttle() to solve similar problems.
Transcript from the "Timing: Debounce Solution" Lesson
[00:00:00]
>> Debounce. If you've never thought about how it works or an autocomplete, or I don't know any type of head solution, we're gonna learn how now. If you have this probably, it's a little trickier because it's hard to mentally picture if you've never given any consideration. Let's go and solve this one.
[00:00:21]
This one, I know I keep saying they're all little tricky, cuz I consider these all a little tricky. I'll never say this one's an easy one. Maybe reversing a string was not too, that's a good warm up question. But this one is a little tricky if you've never considered it.
[00:00:35]
Let's go and type it out. So debounce, what we're gonna do is the signature would look something like debounce, thank you autocomplete, and it would take a function in time. That means every time I wanna invoke this function later, say some other function. Function 1, if I wanna invoke it later, it'll fire here.
[00:00:59]
But it won't actually execute what I wanted to do until the time has passed sufficiently. So again in the type of head, let's say mdn, we're looking at flat map earlier. If we're doing something like say fetching results, we wouldn't want as I type along, a million requests going out.
[00:01:20]
We'd only wanna do it when I've stopped typing. And then the function actually executes. And once we're done with this I'll show you how to implement throttle, which is a little different. Which means, as we type, it'll fire the first one but it won't fire the subsequent ones.
[00:01:38]
And then it'll wait and then it'll fire the first one and fire the subsequent ones. Versus debounce, which hopefully if I've explained it correctly, it will fire once you're done doing the thing. So every time a new action comes in, say that event list fires again, it's gonna stop the previous executions before they were able to execute and then wait.
[00:01:58]
It's gonna wait until it's done. All right, I know I talked a lot, so let's implement debounce. So again, it's a function. I think everything today has been a function. And it's gonna take some other function and time. And that earlier example, we want debounced function. And we're gonna wanna execute that.
[00:02:24]
So, say this is in an event listener or something like that. So, what's the trick? If it's a function that you're gonna execute later, you're going to at some point wanna return that function. Okay, What else do we wanna do? We know this is involving timing. So if I wanna say I only want this executed every ten seconds or something like that.
[00:02:49]
So set interval is something I'm gonna use because there's two ways to do timing, set interval or set time out. Actually I don't want set interval, I want set time outs. And set time outs gonna take some function, not this function. Close it off, it's going to take the time.
[00:03:10]
So I'm gonna pass in this time argument that I got from up here. And then once the time has expired as in the 10 seconds or 500 milliseconds or whatever you want has run down. I wanna invoke the function that I was originally trying to call. So how do we evoke a function?
[00:03:26]
We learned that in the previous exercise. Call or apply, right? So when this is done, when the timer has run out I wanna actually call the function itself. So we'll say fn.apply, and we'll give it the context of this, and we'll pass in the arguments, which is pretty good.
[00:03:47]
I could actually just leave that off. But if I'm trying to be specific I could say arguments. Hm, okay, that's that's something, but what will happen if we execute this debounce function? What will happen now, anybody, nobody? It's okay, I know we've been solving problems for a while now, like a real tactile interview.
[00:04:22]
Yes, Ratel.
>> I didn't solve the problem.
>> That's okay.
>> [LAUGH] That's gonna fire five events, right?
>> Yeah, it will, it'll set up five, or, one, two, three, four, five. Yes, that's five, it will set up five set timeouts, which will at the end of the time that we pass in will all fire.
[00:04:41]
That's not what we want at all. At this point, we're just delaying execution that function. What we want is if there's already a function being executed, so think of the autocomplete example. If they're still typing, we don't wanna fire this function apply until they're finished doing the action that we want.
[00:04:58]
And then we have the complete data that we wanna execute on, then we fire that. So a way of doing that is remembering that set timeout set interval return and ID. So we'll say setTimeoutId. And in this scope, I'm gonna say setTimeoutId. We're gonna set it to null for now.
[00:05:23]
All right, so now we have at least a reference, if there's something already running. And if there's something running, we wanna cancel it because the person still typing in this example, we wanna cancel that. So how do I check if something exists in JavaScript? I say If, so if the setTimeoutId, if it exists, we wanna cancel whatever else was coming before.
[00:05:46]
So instead of setting five set timeouts, we only wanna set one. That means we cancel anything else that was before it. So we're gonna clear interval. Or was it interval? No, sorry, clear timeout. I wouldn't penalize you if you got it wrong. Set TimeoutId. Okay, so now what happens when we call this in a row?
[00:06:14]
Which one of these is going to get executed?
>> The last one.
>> Yes, the last one, because we're coming through. This is we're sending a timeout, so we have a TimeoutId. The next time we invoke this function it's gonna say, there's a TimeoutId, I'm gonna cancel that last one so it never fires.
[00:06:32]
It's like it never existed. And that's going to keep doing that until this function is called. But there's one missing step we need to do, which is what happens when this function is called?
>> Get rid of the TimeoutId.
>> Exactly, we need to get rid of the TimeoutId.
[00:06:50]
Because otherwise, we're gonna get here, and it will just be stuck, it'll never execute anything. So we're just gonna say, setTimeoutId, we'll say it's equal to null. And that's how to implement debounce. If you've never seen it before or thought about how it's implemented, it's a little challenging.
[00:07:12]
But once you see it, you start to think okay, I need to return a function that's gonna work at some other point. Now that's debounce. If we wanna implement throttle, very similar concept. Except throttle just says, I wanna execute this first one, and I don't wanna execute anything else that comes after it until the time has expired.
[00:07:33]
So instead of clearing the timeout, we say if there's a timeout, I would just return. Cuz it's saying, there's already something running and the time hasn't expired yet. All right cool, I'll just return. So none of these would fire. This one would fire. None of these would fire until the time has elapsed.
[00:07:51]
And that's how to implement throttle. And you see you can gradually build up a really powerful way of timing things, or setting things at certain intervals, if you can implement debounce or throttle or something like that. All right, I know that one was challenging if you've never seen it before.
[00:08:11]
But hopefully now we understand set timeouts and intervals and all that good stuff.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops