Tips for restricting function invocations in JavaScript?

I am seeking a function called limitCalls(fn, maxCalls) which accepts a function fn and creates a new function that can only be called the specified number of times in maxCalls. Here is a test example:

 it('limitCalls', () => {
const makeIncrement = () => {
  let count = 0;

  return () => {
    count += 1;
    return count;
  };
};

const limitedIncrementA = limitCalls(makeIncrement(), 3);

expect(limitedIncrementA()).toBe(1);
expect(limitedIncrementA()).toBe(2);
expect(limitedIncrementA()).toBe(3);
expect(limitedIncrementA()).toBe(undefined);
expect(limitedIncrementA()).toBe(undefined);

const limitedIncrementB = limitCalls(makeIncrement(), 1);

expect(limitedIncrementB()).toBe(1);
expect(limitedIncrementB()).toBe(undefined);
expect(limitedIncrementB()).toBe(undefined);

});

This is my implementation so far:

var calls = 0;
export default function limitCalls(fn, maxCalls) {
  if (calls >= maxCalls) {
    return undefined;
  }
  calls += 1;
  return fn();
}

The error I am encountering is "limitedIncrementA is not a function." Please assist me with resolving this issue.

Answer №1

Instead of conditionally returning a function, always return a function that conditionally executes the fn callback:

function limitCalls(fn, maxCalls) {
  let count = 0;
  
  return function(...args) {
    return count++ < maxCalls ? fn(...args) : undefined;
  }
}

const limited = limitCalls(console.log, 3);

limited('one');
limited('two');
limited('three');
limited('four');

Answer №2

Within this code snippet, it is important to note that limitedIncrementA does not function as expected. Take a look at the following details:

/* When you use makeIncrement in this context,
   the result is passed to 'limitCalls'
 */
const limitedIncrementA = limitCalls(makeIncrement(), 3);

/* In contrast, when you pass makeIncrement as is,
   you are providing a reference to the function itself
   that can be utilized within 'limitCalls'
 */
const limitedIncrementB = limitCalls(makeIncrement, 3);

Therefore, assuming that makeIncrement produces incremental values (1, 2, 3, ...), your current implementation is essentially like this:

limitCalls(1, 3);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Experiencing difficulties launching my Server.JS due to a listening error

Hey there, I'm struggling to get my server.js up and running. Whenever I try to run node on it, I keep getting the error message "listening on *:3000". Below is the code for my server.js: var app = require('express')(); var http = require(&a ...

How can we identify if the user is utilizing a text-input control?

Incorporating keyboard shortcuts into my HTML + GWT application is a goal of mine, but I am hesitant about triggering actions when users are typing in a text area or utilizing the keyboard for select menu operations. I am curious if there exists a method ...

"I'm looking for a solution on integrating Osano CookieConsent into my Next.js application. Can

I'm facing a bit of a challenge with incorporating the Osano Cookie Consent JavaScript plugin into my nextjs app. I've been attempting to set up the cc object by initializing it in the useEffect of my root landing page: const CC = require( " ...

Adjust the height of an element using CSS based on the height of another

Is there a way to have two divs per row, where the second div always displays its full content and the height of the first div matches the height of the second div? If the content in the first div exceeds the height, it should be scrollable. I've atte ...

The Enigma of AngularJS Coding

Check out this code snippet. $scope.$watch('year', reloadData); $scope.$watch('month', reloadData); $scope.year = 2017; $scope.month = 1; var reloadData = function() { /* Refresh Data */ } var init = function() { $scope.year ...

Display an Asterisk Icon for md-input fields with lengthy labels

Documentation states that md-inputs add an asterisk to the label if it is a required type. However, when input containers have width constraints and long labels, the label gets truncated and the asterisk becomes invisible. From a user experience perspectiv ...

Exploring the world of MVC4: Enhancing user experience with client-side

Solution: The answer provided by @www.innovacall.com is correct, I initially misunderstood it but now it works perfectly. Thank you for the help. Initial issue: I have been struggling with finding a solution to my problem. In my project, there is a mod ...

The CloudWatch logs for a JavaScript Lambda function reveal that its handler is failing to load functions that are defined in external

Hello there, AWS Lambda (JavaScript/TypeScript) is here. I have developed a Lambda handler that performs certain functions when invoked. Let me walk you through the details: import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda' ...

How can I combine an onkeypress and onclick event listener in one method?

I have two inquiries, somewhat intertwined. 1) Is it feasible to merge the 2 functions below into a more efficient function, or do I need to create a function and then call it in both event listeners? input.addEventListener("keyup", () => { if (eve ...

What is the method used by React or Next to prevent the <a> tag from refreshing the page while still loading content?

I'm currently diving into the world of NextJS and utilizing the Link component from the 'next/link' package. One thing that has been puzzling me is how the <Link> component ultimately renders an <a> tag with a href='/tosomew ...

Building custom components in Vue.js/NuxtJS can be a breeze when using a default design that can be easily customized through a JSON configuration

Currently, I am in the process of developing a NuxtJS website where the pages and components can either have a generic design by default or be customizable based on client specifications provided in the URL. The URL structure is as follows: http://localh ...

Navigating to an AngularJS state through an email hyperlink

Trying to guide users from an email link to a specific state within my Angular app presents a challenge due to its single page nature, making direct URL redirection impossible. Past attempts involved utilizing URL parameters: The email includes this link ...

Issues with jQuery requests not working properly on the mobile application

Creating a mobile application for Android devices using Intel XDK has been a rewarding experience so far. I have been testing my PHP code on an emulator and local development server (127.0.0.1) through AJAX methods such as $.ajax(), $.post(), and $.get(). ...

When the jQuery document is ready, it typically returns null, but the console can still access and display

I have encountered an issue while working on a solution within a CMS (EPiServer). When I utilize console.log to check my object, it displays a null value. $(document).ready(function () { console.log("$('.EPiRequester').html() =" + $('. ...

Various gulp origins and destinations

I am attempting to create the following directory structure -- src |__ app |__ x.ts |__ test |__ y.ts -- build |__ app |__ js |__ test |__ js My goal is to have my generated js files inside buil ...

Find the total of values in an array that may be null or undefined

In this scenario, I have an array that looks like this: myData = [[2, null, null, 12, 2], [0, 0, 10, 1, null], undefined]; The goal is to calculate the sum of each sub-array, resulting in an array like this: result = [16, 11, 0]. The ...

A guide to implementing infinite scrolling with vue-infinite-loading in Nuxt.js (Vue.js)

Currently, I am working on developing a web application using Nuxt.js (Vue.js). Initially, to set up the project, I used the command: vue init nuxt/express MyProject ~page/help.vue <template> <div> <p v-for="item in list"> ...

How to create a sequence of queries to a mongoDB database (using mongoose) depending on a condition

Source Code let placeForSearch="hampi" let filteredHotelFacilities=req.body.filter //["Free Wifi"] let hotels = await Hotel.find({placeForSearch}) .where("facilities") .select(selectedProperties) .skip(pageNu ...

What steps should I take to address both the issue of duplicate names and the malfunctioning fixtures?

There are issues with duplicate item names and the cache not updating immediately after running the script. Instead of fetching new data, it retrieves previous values from the last item shop sections. If the remove_duplicates function is not used, it displ ...

Is there a way to fix the error "The requested resource does not have the 'Access-Control-Allow-Origin' header" within Express using Firebase functions?

Trying to send an email through nodemailer using Firebase functions, but encountering errors. The data for the email will come from a form. Error message: Access to XMLHttpRequest at 'my-firebase-functions' from origin 'my-angular-web-app&a ...