'Pass an extra argument to a callback function

I have a function callWithMagic which takes a callback function as a parameter and calls it with one argument.

const callWithMagic = callback => {
  const magic = getMagic();
  callback(magic);
};

I also have a function processMagic which takes two arguments: magic and theAnswer.

const processMagic = (magic, theAnswer) => {
  someOtherMagic();
};

I want to pass the function processMagic as an argument to callWithMagic, but I also want to pass 42 as the second parameter (theAnswer) to processMagic. How can I do that?

callWithMagic(<what should I put here?>);


Solution 1:[1]

You could use an anonymus function

something like

session.sub('Hello', function(){marketEvents(your args);});

Solution 2:[2]

You can create a function which calls the marketEvent function. No need to complicate things

session.sub('Hello', function(args, kwargs) {
    marketEvent(args, kwargs, 'my custom data');
});

otherwise you can do this:

var mrktEvent = function(customArgs) {
    return function(args, kwargs) { 
        marketEvent(args, kwargs, customArgs) 
    };
}

session.sub('Hello', mrktEvent("customEvent"));

Solution 3:[3]

I want to pass the function processMagic as an argument to callWithMagic, but I also want to pass 42 as the second parameter theAnswer to processMagic. How can I do that?

Okay first, your implementation was almost close to the answer. You want to call your function like this callWithMagic(<what should I put here?>). Also I noticed that you use ECMAScript 6: arrow functions so we'll simplify our code a lot.

So, callWithMagic(<what should I put here?>); can use these parameters callWithMagic(processMagic, 42); where the first parameter is the callback function and the other one the extra parameter you want to add.

To call this function with the extra parameter, we need to modify the callWithMagic implementation by defining a new parameter that will be answer like this:

const callWithMagic = (callback, answer) => {
  const magic = getMagic()
  callback(magic, answer)
}

Now, here you have a working snippet of your implementation:

const spells = ["Accio", "Aguamenti", "Alohomora", "Aparecium", "Avada Kedavra", "Avifors", "Avis", "Bombarda", "Colloportus", "Confringo", "Confundus", "Crucio", "Deletrius", "Densaugeo", "Diffindo", "Dissendium", "Engorgio", "Episkey", "Evanesco", "Expecto Patronum", "Expelliarmus", "Fera Verto", "Ferula", "Fidelius", "Finite Incantatem", "Flagrate", "Flipendo", "Furnunculus", "Geminio", "Homorphus", "Immobulus", "Impedimenta", "Imperio", "Impervius", "Incarcerous", "Incendio", "Legilimens", "Levicorpus", "Liberacorpus", "Locomotor Mortis", "Lumos", "Mobiliarbus", "Mobilicorpus", "Morsmordre", "Muffliato", "Nox", "Obliviate", "Orchideous", "Petrificus Totalus", "Prior Incantato", "Protego", "Reducio", "Reducto", "Relashio", "Rennervate", "Reparo", "Repello", "Repello Muggletum", "Revelio", "Rictusempra", "Riddikulus", "Salvio Hexia", "Scourgify", "Sectumsempra", "Serpensortia", "Silencio", "Sonorus", "Stupefy", "Tarantallegra", "Tergeo", "Waddiwasi", "Wingardium Leviosa"]
const len = spells.length

function random(max) {
  return Math.floor(Math.random() * max)
}

const getMagic = () => {
  return spells[random(len)]
}

const callWithMagic = (callback, answer) => {
  const magic = getMagic()
  callback(magic, answer)
}

const someOtherMagic = (magic, answer) => {
  console.log({magic, answer})
}

const processMagic = (magic, answer) => {
  someOtherMagic(magic, answer)
}

callWithMagic(processMagic, 42)

Teo, seems good but it is to long, can we simplify this?

Well, yes. We just need the concept of closure. The idea is to create a wrapper callback like function() {}. This will be the parameter for callWithMagic. Now let's modify callWithMagic to receive the wrapper callback:

const callWithMagic = function(f) {
  f()
}

or using arrow functions:

const callWithMagic = f => f()

Let's see how it works:

const spells = ["Accio", "Aguamenti", "Alohomora", "Aparecium", "Avada Kedavra", "Avifors", "Avis", "Bombarda", "Colloportus", "Confringo", "Confundus", "Crucio", "Deletrius", "Densaugeo", "Diffindo", "Dissendium", "Engorgio", "Episkey", "Evanesco", "Expecto Patronum", "Expelliarmus", "Fera Verto", "Ferula", "Fidelius", "Finite Incantatem", "Flagrate", "Flipendo", "Furnunculus", "Geminio", "Homorphus", "Immobulus", "Impedimenta", "Imperio", "Impervius", "Incarcerous", "Incendio", "Legilimens", "Levicorpus", "Liberacorpus", "Locomotor Mortis", "Lumos", "Mobiliarbus", "Mobilicorpus", "Morsmordre", "Muffliato", "Nox", "Obliviate", "Orchideous", "Petrificus Totalus", "Prior Incantato", "Protego", "Reducio", "Reducto", "Relashio", "Rennervate", "Reparo", "Repello", "Repello Muggletum", "Revelio", "Rictusempra", "Riddikulus", "Salvio Hexia", "Scourgify", "Sectumsempra", "Serpensortia", "Silencio", "Sonorus", "Stupefy", "Tarantallegra", "Tergeo", "Waddiwasi", "Wingardium Leviosa"]
const len = spells.length

const random = max => Math.floor(Math.random() * max)

const callWithMagic = callback => callback()

const getMagic = () => spells[random(len)]

const someOtherMagic = (magic, answer) => console.log({magic, answer})

const processMagic = (magic, answer) => someOtherMagic(magic, answer)

callWithMagic(function() {
  const magic = getMagic()
  return processMagic(magic, 42)
})

Now let's simplify callWithMagic as const callWithMagic = f => f().

const magic = getMagic()
callWithMagic(magic => processMagic(magic, 42))

const spells = ["Accio", "Aguamenti", "Alohomora", "Aparecium", "Avada Kedavra", "Avifors", "Avis", "Bombarda", "Colloportus", "Confringo", "Confundus", "Crucio", "Deletrius", "Densaugeo", "Diffindo", "Dissendium", "Engorgio", "Episkey", "Evanesco", "Expecto Patronum", "Expelliarmus", "Fera Verto", "Ferula", "Fidelius", "Finite Incantatem", "Flagrate", "Flipendo", "Furnunculus", "Geminio", "Homorphus", "Immobulus", "Impedimenta", "Imperio", "Impervius", "Incarcerous", "Incendio", "Legilimens", "Levicorpus", "Liberacorpus", "Locomotor Mortis", "Lumos", "Mobiliarbus", "Mobilicorpus", "Morsmordre", "Muffliato", "Nox", "Obliviate", "Orchideous", "Petrificus Totalus", "Prior Incantato", "Protego", "Reducio", "Reducto", "Relashio", "Rennervate", "Reparo", "Repello", "Repello Muggletum", "Revelio", "Rictusempra", "Riddikulus", "Salvio Hexia", "Scourgify", "Sectumsempra", "Serpensortia", "Silencio", "Sonorus", "Stupefy", "Tarantallegra", "Tergeo", "Waddiwasi", "Wingardium Leviosa"]
const len = spells.length

const random = max => Math.floor(Math.random() * max)

const callWithMagic = f => f()

const getMagic = () => spells[random(len)]

const someOtherMagic = (magic, answer) => console.log({magic, answer})

const processMagic = (magic, answer) => someOtherMagic(magic, answer)

callWithMagic(() => {
  const magic = getMagic()
  processMagic(magic, 42)
})

Solution 4:[4]

You can bind argument object to callback function:

var varObject = {var1: "findButton", var2: true};

function cbFunc() {
    console.log(this.var1+ ":" + this.var2);
}

//Example callback
datatable.ajax.reload(cbFunc.bind(varObject));

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Dropye
Solution 2 TryingToImprove
Solution 3
Solution 4 aecavac