what is wrong here

i know to solve this problem we will use apply but i don't understand why?
No description
6 Replies
dys πŸ™
dys πŸ™β€’11mo ago
const once = (fn) => {
let i = 0
return (...args) => {
if(i++ === 0) {
return fn.call(this, ...args)
}
}
}
const oncefn = once((a, b, c) => a + b + c)
console.dir(oncefn(1, 2, 3)) // 6
console.dir(oncefn(1, 2, 3)) // undefined
console.dir(oncefn(1, 2, 3)) // undefined
const once = (fn) => {
let i = 0
return (...args) => {
if(i++ === 0) {
return fn.call(this, ...args)
}
}
}
const oncefn = once((a, b, c) => a + b + c)
console.dir(oncefn(1, 2, 3)) // 6
console.dir(oncefn(1, 2, 3)) // undefined
console.dir(oncefn(1, 2, 3)) // undefined
MarkBoots
MarkBootsβ€’11mo ago
The code defines a function once that takes another function fn as its argument. The purpose of the once function is to create a new function that can only be called once. The inner function returned by once keeps track of the number of times it has been called using the variable i. If the inner function is called for the first time (i.e., i is 0), it invokes the original function fn with the provided arguments (...args) and increments the counter i. Subsequent calls to the inner function have no effect. So in short: You do this to limit the amount of times a function can be called i don't really have a use case in mind though
Skylark
Skylarkβ€’11mo ago
You might want to use it for if running it more than once is destructive such as if you have a function that you pass around which is then used to add to a database. Although avoiding running it more than once is best done another way You could have a function which takes no arguments and when you run it the result is memoised and when you call it again you get back that value. I feel like the exact setup provided isn’t particularly useful and is best done in a less confusing way elsewhere
Moataz
MoatazOPβ€’11mo ago
thanks thanks
Chooβ™šπ•‚π•šπ•Ÿπ•˜
I prefer this approach:
const once = (fn) => {
let hasRun = false;
return () => {
if(!hasRun){
fn();
hasRun = true;
}
}
}
const print5once = once(()=>{console.log(5)});
print5once(); // outputs 5
print5once(); // nothing happens
print5once(); // nothing happens
print5once(); // nothing happens
print5once(); // nothing happens
const once = (fn) => {
let hasRun = false;
return () => {
if(!hasRun){
fn();
hasRun = true;
}
}
}
const print5once = once(()=>{console.log(5)});
print5once(); // outputs 5
print5once(); // nothing happens
print5once(); // nothing happens
print5once(); // nothing happens
print5once(); // nothing happens
No error is thown. It just runs the function once and does nothing if it is called again. An example of a situation in which this would be useful is the "place order" operation in an e-commerce site that operates as a single page app. If you don't guard against the operation being performed multiple times, the customer may buy more times than they intended. This will not only result in unhappy distrustful customers who will never come back. This also requires extra work to reverse the charges, which increases labor costs, and having many chargebacks will result in the credit card companies charging higher processing fees.
Skylark
Skylarkβ€’11mo ago
I was going to suggest a checkout but I thought of a reason why it would just be better to not do it like that. I know that you then have to set it up again if the checkout fails but that wasn’t the big issue. It’ll come to me You could have something like
const once_resettable = (fn) => {
let has_run = false;
return [
() => {
if(has_run) return;
has_run = true;
return fn();
},
() => {
has_run = false;
}
];
};

const [log_five_once, reset_log_five] = once_resettable(() => console.log(5));
log_five_once(); // logs 5
log_five_once(); // nothing
reset_log_five();
log_five_once(); // logs 5
const once_resettable = (fn) => {
let has_run = false;
return [
() => {
if(has_run) return;
has_run = true;
return fn();
},
() => {
has_run = false;
}
];
};

const [log_five_once, reset_log_five] = once_resettable(() => console.log(5));
log_five_once(); // logs 5
log_five_once(); // nothing
reset_log_five();
log_five_once(); // logs 5
So it makes it easier to allow the user to submit again after there has been an error and the error has been checked, just run the reset function. Also return the result of fn() rather than just run it, and I moved the hasRun check into a non-negated guard clause. Additionally you can memoise the result and return that, or return a default value rather than undefined
Want results from more Discord servers?
Add your server