2010-08-11 18 views
215

Estoy tratando de pasar algún parámetro a una función utilizada como devolución de llamada, ¿cómo puedo hacer eso?JavaScript: paso de parámetros a una función de devolución de llamada

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

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

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

Lo que está haciendo debe trabajar. ¿Qué problemas tienes? –

+1

Tu código funciona bien, ¿cuál es el problema? – Sarfraz

+1

Debería funcionar ... http://jsfiddle.net/QXQZj/ – Hristo

Respuesta

186

Si quieres algo un poco más general, puede utilizar los argumentos variable de este modo:

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

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

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

Pero por lo demás, el ejemplo funciona bien (argumentos [0] se pueden utilizar en lugar de devolución de llamada en el probador)

+42

Mientras estemos en el espíritu de ser generales, 'callback.apply (arguments)' como el cuerpo de la función para 'callbackTester' es extensible más allá del escenario de dos argumentos. –

+0

lo siento, era un error de sintaxis en el código principal, pensé que era esto porque esta es la primera vez que uso una devolución de llamada en JavaScript, me has ayudado a entender que no era el problema, y ​​para ver un gran ejemplo – vitto

+1

FYI, usar una función anónima (respuesta de Marimuthu) o .bind() (respuesta de Andy) son formas mucho más claras de pasar argumentos a una devolución de llamada. – antoine

50

Su pregunta no está clara. Si está preguntando cómo puede hacer esto de una manera más simple, debe echar un vistazo al método ECMAScript 5th edition .bind(), que es miembro de Function.prototype. Al usarlo, usted puede hacer algo como esto:

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

function callbackTester (callback) { 
    callback(); 
} 

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

También puede utilizar el siguiente código, que añade el método si no está disponible en el navegador actual:

// 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))); 
    }; 
    }; 
} 

Example

bind() - PrototypeJS Documentation

+0

Fuera de interés, ¿cuál es la diferencia entre 'Array.prototype.slice.call (arguments)' y 'arguments.slice()'? – sje397

+6

@ sje397: * arguments * no es una matriz \ * real \ *, por lo que no tiene un método * slice() *. Sin embargo, el método * slice() * en el * Array.prototype * es intencionalmente genérico, por lo que puede pasar cualquier objeto que tenga índices numéricos y una propiedad * length * y funcionará. –

+0

Aha. Cheers .... – sje397

176

Esto también funcionaría:

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

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

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

otro escenario:

// 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); 
}); 
+21

+1. Pasar in closures/funciones anónimas es la mejor manera. –

+0

¿Cómo borraría Interval entonces? –

+2

Esto funciona muy bien porque también permite que la función anónima pase parámetros como los siguientes: callbackTester (función (datos) {tryMe (datos, "hola", "adiós");}); –

9

Cuando se tiene una devolución de llamada que será llamado por algo distinto de su código con un número específico de params y desea pasar en params adicionales que puede pasar una función envoltura como la devolución de llamada y dentro del envoltorio pasar los param (s) adicionales.

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 
} 
4

englobar la función 'niño' (s) que se pasa como/con argumentos dentro de envolturas de función para evitar que se está evaluando cuando la función de 'padre' se llama.

function outcome(){ 
    return false; 
} 

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

process(function(){alert("OKAY");},function(){alert("OOPS");}) 
3

Código partir de una pregunta con cualquier número de parámetros y un contexto de devolución de llamada:

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 
0

Una nueva versión para el escenario en el que la devolución de llamada será llamado por alguna otra función, no su propio código, y quieres agregar parámetros adicionales.

Por ejemplo, imaginemos que tiene muchas llamadas anidadas con éxito y devoluciones de llamada de error. Usaré promesas angulosas para este ejemplo, pero cualquier código de javascript con devolución de llamada sería el mismo para ese propósito.

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); 
}); 

Ahora es posible que desee eliminar el desorden de su código mediante la definición de una función para registrar los errores, manteniendo el origen del error para fines de depuración.Así es como se procedería a refactorizar su código:

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 función que llama todavía añadir el parámetro de error después de que sus parámetros de la función de devolución de llamada.

0

Estaba buscando lo mismo y terminar con la solución y aquí es un ejemplo simple si alguien quiere pasar por esto.

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') 

también se publican en la otra pregunta here

1

Uso función curry como en este ejemplo sencillo.

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>

Cuestiones relacionadas