web-dev-qa-db-fra.com

JavaScript: Passage de paramètres à une fonction de rappel

J'essaie de passer un paramètre à une fonction utilisée comme rappel, comment puis-je faire cela?

function tryMe (param1, param2) {
    alert (param1 + " and " + param2);
}

function callbackTester (callback, param1, param2) {
    callback (param1, param2);
}

callbackTester (tryMe, "hello", "goodbye");
253
vitto

Si vous voulez quelque chose de légèrement plus général, vous pouvez utiliser la variable arguments comme ceci:

function tryMe (param1, param2) {
    alert(param1 + " and " + param2);
}

function callbackTester (callback) {
    callback (arguments[1], arguments[2]);
}

callbackTester (tryMe, "hello", "goodbye");

Mais sinon, votre exemple fonctionne bien (les arguments [0] peuvent être utilisés à la place du rappel dans le testeur)

227
Simon Scarfe

Cela fonctionnerait aussi:

// callback function
function tryMe (param1, param2) { 
    alert (param1 + " and " + param2); 
} 

// callback executer 
function callbackTester (callback) { 
    callback(); 
} 

// test function
callbackTester (function() {
    tryMe("hello", "goodbye"); 
}); 

Un autre scénario:

// callback function
function tryMe (param1, param2, param3) { 
    alert (param1 + " and " + param2 + " " + param3); 
} 

// callback executer 
function callbackTester (callback) { 
//this is the more obivous scenario as we use callback function
//only when we have some missing value
//get this data from ajax or compute
var extraParam = "this data was missing" ;

//call the callback when we have the data
    callback(extraParam); 
} 

// test function
callbackTester (function(k) {
    tryMe("hello", "goodbye", k); 
}); 
189
Marimuthu Madasamy

Votre question n'est pas claire. Si vous demandez comment vous pouvez le faire d'une manière plus simple, consultez la méthode .bind () d'ECMAScript 5th edition, qui est membre de Function.prototype. En l'utilisant, vous pouvez faire quelque chose comme ceci:

function tryMe (param1, param2) {
    alert (param1 + " and " + param2);
}

function callbackTester (callback) {
    callback();
}

callbackTester(tryMe.bind(null, "hello", "goodbye"));

Vous pouvez également utiliser le code suivant, qui ajoute la méthode si elle n'est pas disponible dans le navigateur actuel:

// From Prototype.js
if (!Function.prototype.bind) { // check if native implementation available
  Function.prototype.bind = function(){ 
    var fn = this, args = Array.prototype.slice.call(arguments),
        object = args.shift(); 
    return function(){ 
      return fn.apply(object, 
        args.concat(Array.prototype.slice.call(arguments))); 
    }; 
  };
}

Exemple

bind () - PrototypeJS Documentation

55
Andy E

Lorsque vous avez un rappel qui sera appelé par quelque chose d'autre que votre code avec un nombre spécifique de paramètres et que vous souhaitez transmettre des paramètres supplémentaires, vous pouvez passer une fonction wrapper en tant que rappel et à l'intérieur du wrapper, passer le ou les paramètres supplémentaires. 

function login(accessedViaPopup) {
    //pass FB.login a call back function wrapper that will accept the
    //response param and then call my "real" callback with the additional param
    FB.login(function(response){
        fb_login_callback(response,accessedViaPopup);
    });
}

//handles respone from fb login call
function fb_login_callback(response, accessedViaPopup) {
    //do stuff
}
10
Blake Mills

Enveloppez les fonctions 'enfant' passées en tant que/avec des arguments dans les enveloppes de fonctions pour éviter leur évaluation lors de l'appel de la fonction 'parent'.

function outcome(){
    return false;
}

function process(callbackSuccess, callbackFailure){
    if ( outcome() )
        callbackSuccess();
    else
        callbackFailure();
}

process(function(){alert("OKAY");},function(){alert("OOPS");})
4
Alan McCune

Code d'une question avec un nombre quelconque de paramètres et un contexte de rappel:

function SomeFunction(name) {
    this.name = name;
}
function tryMe(param1, param2) {
    console.log(this.name + ":  " + param1 + " and " + param2);
}
function tryMeMore(param1, param2, param3) {
    console.log(this.name + ": " + param1 + " and " + param2 + " and even " + param3);
}
function callbackTester(callback, callbackContext) {
    callback.apply(callbackContext, Array.prototype.splice.call(arguments, 2));
}
callbackTester(tryMe, new SomeFunction("context1"), "hello", "goodbye");
callbackTester(tryMeMore, new SomeFunction("context2"), "hello", "goodbye", "hasta la Vista");

// context1: hello and goodbye
// context2: hello and goodbye and even hasta la Vista
4

Si vous n'êtes pas sûr du nombre de paramètres que vous allez passer dans les fonctions de rappel. En utilisant appliquer.

function tryMe (param1, param2) {
  alert (param1 + " and " + param2);
}

function callbackTester(callback,params){
    callback.apply(this,params);
}

callbackTester(tryMe,['hello','goodbye']);
3
Zeeman Chen

Utilisez la fonction curry comme dans cet exemple simple.

const BTN = document.querySelector('button')
const RES = document.querySelector('p')

const changeText = newText => () => {
  RES.textContent = newText
}

BTN.addEventListener('click', changeText('Clicked!'))
<button>ClickMe</button>
<p>Not clicked<p>

2
user6748331

Laissez-moi vous donner un exemple très simple de style Node.js d'utilisation d'un rappel:

/**
 * Function expects these arguments: 
 * 2 numbers and a callback function(err, result)
 */
var myTest = function(arg1, arg2, callback) {
  if (typeof arg1 !== "number") {
    return callback('Arg 1 is not a number!', null); // Args: 1)Error, 2)No result
  }
  if (typeof arg2 !== "number") {
    return callback('Arg 2 is not a number!', null); // Args: 1)Error, 2)No result
  }
  if (arg1 === arg2) {
    // Do somethign complex here..
    callback(null, 'Actions ended, arg1 was equal to arg2'); // Args: 1)No error, 2)Result
  } else if (arg1 > arg2) {
    // Do somethign complex here..
    callback(null, 'Actions ended, arg1 was > from arg2'); // Args: 1)No error, 2)Result
  } else {
    // Do somethign else complex here..
    callback(null, 'Actions ended, arg1 was < from arg2'); // Args: 1)No error, 2)Result
  }
};


/**
 * Call it this way: 
 * Third argument is an anonymous function with 2 args for error and result
 */
myTest(3, 6, function(err, result) {
  var resultElement = document.getElementById("my_result");
  if (err) {
    resultElement.innerHTML = 'Error! ' + err;
    resultElement.style.color = "red";
    //throw err; // if you want
  } else {
    resultElement.innerHTML = 'Result: ' + result;
    resultElement.style.color = "green";
  }
});

et le HTML qui rendra le résultat:

<div id="my_result">
  Result will come here!
</div>

Vous pouvez y jouer ici: https://jsfiddle.net/q8gnvcts/ - par exemple, essayez de passer une chaîne au lieu du nombre: myTest ('une chaîne', 6, fonction (err, résultat) .. et voir le résultat.

J'espère que cet exemple aide car il représente l'idée de base des fonctions de rappel.

0
Vlado

Une nouvelle version du scénario dans laquelle le rappel est appelé par une autre fonction, et non par votre propre code, et vous souhaitez ajouter des paramètres supplémentaires.

Par exemple, supposons que vous avez beaucoup d'appels imbriqués avec des rappels de succès et d'erreur. Je vais utiliser des promesses angulaires pour cet exemple, mais tout code javascript avec des rappels serait le même pour les besoins.

someObject.doSomething(param1, function(result1) {
  console.log("Got result from doSomething: " + result1);
  result.doSomethingElse(param2, function(result2) {
    console.log("Got result from doSomethingElse: " + result2);
  }, function(error2) {
    console.log("Got error from doSomethingElse: " + error2);
  });
}, function(error1) {
  console.log("Got error from doSomething: " + error1);
});

Vous pouvez maintenant désencombrer votre code en définissant une fonction permettant de consigner les erreurs, en conservant l'origine de l'erreur à des fins de débogage. Voici comment procéder pour refactoriser votre code:

someObject.doSomething(param1, function (result1) {
  console.log("Got result from doSomething: " + result1);
  result.doSomethingElse(param2, function (result2) {
    console.log("Got result from doSomethingElse: " + result2);
  }, handleError.bind(null, "doSomethingElse"));
}, handleError.bind(null, "doSomething"));

/*
 * Log errors, capturing the error of a callback and prepending an id
 */
var handleError = function (id, error) {
  var id = id || "";
  console.log("Got error from " + id + ": " + error);
};

La fonction appelante ajoutera toujours le paramètre error après vos paramètres de fonction de rappel.

0
Juangui Jordán
function tryMe(param1, param2) {
  console.log(param1 + " and " + param2);
}

function tryMe2(param1) {
  console.log(param1);
}

function callbackTester(callback, ...params) {
  callback(...params);
}



callbackTester(tryMe, "hello", "goodbye");

callbackTester(tryMe2, "hello");

en savoir plus à propos de la syntaxe de propagation

0
Dmitry Grinko

Je cherchais la même chose et je trouve la solution. En voici un exemple simple si quelqu'un veut passer par là.

var FA = function(data){
   console.log("IN A:"+data)
   FC(data,"LastName");
};
var FC = function(data,d2){
   console.log("IN C:"+data,d2)
};
var FB = function(data){
   console.log("IN B:"+data);
    FA(data)
};
FB('FirstName')

Également publié sur l'autre question ici

0
Code_Crash