JavaScript: Übergabe von Parametern an eine Rückruffunktion


289

Ich versuche, einen Parameter an eine als Rückruf verwendete Funktion zu übergeben. Wie kann ich das tun?

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

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

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

9
Was Sie tun, sollte funktionieren. Welche Probleme hast du?
Daniel Vassallo

1
Ihr Code funktioniert gut, was ist das Problem?
Sarfraz

1
Es sollte funktionieren ... jsfiddle.net/QXQZj
Hristo

Es tut mir leid, dass ich an der Syntax des
Hauptcodes

Wenn Sie einem Rückruf Parameter hinzufügen möchten, aber nicht ändern können, was ihn aufruft (da Sie nicht in der Lage sind, die Argumentreihenfolge zu ändern, können Sie einige der Rückrufparameter mit JS-Bindung vorbinden, wie ich weiter unten gezeigt habe diese Antwort: stackoverflow.com/a/28120741/1695680
ThorSummoner

Antworten:


253

Wenn Sie etwas allgemeineres möchten, können Sie die Argumentvariable wie folgt verwenden:

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

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

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

Andernfalls funktioniert Ihr Beispiel einwandfrei (Argumente [0] können anstelle des Rückrufs im Tester verwendet werden).


53
Solange wir im Geiste des Allgemeinen sind, ist callback.apply(arguments)der Funktionskörper für callbackTesterüber das Szenario mit zwei Argumenten hinaus erweiterbar.
Steven

1
Entschuldigung, es war ein Syntaxfehler im Hauptcode. Ich dachte, dies ist der Grund, warum ich zum ersten Mal einen Rückruf in JavaScript verwende. Sie haben mir geholfen zu verstehen, dass dies nicht das Problem war, und ein großartiges Beispiel zu sehen.
Vitto

3
Zu Ihrer Information: Die Verwendung einer anonymen Funktion (Marimuthus Antwort) oder .bind () (Andys Antwort) ist eine viel sauberere Möglichkeit, Argumente an einen Rückruf zu übergeben.
Antoine

203

Dies würde auch funktionieren:

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

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

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

Ein weiteres Szenario:

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

2
Dies funktioniert hervorragend, da die anonyme Funktion auch folgende Parameter übergeben kann: callbackTester (function (data) {tryMe (data, "hello", "goodbye");});
Michael Khalili

Ich möchte auch überprüfen, ob der Rückruf tatsächlich eine Funktion ist. if (typeof window[callback] == 'function') window[callback].call(this);
GreeKatrina

63

Ihre Frage ist unklar. Wenn Sie sich fragen, wie Sie dies auf einfachere Weise tun können, sollten Sie sich die ECMAScript 5th Edition-Methode .bind () ansehen , die Mitglied von Function.prototype ist . Mit ihm können Sie so etwas tun:

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

function callbackTester (callback) {
    callback();
}

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

Sie können auch den folgenden Code verwenden, der die Methode hinzufügt, wenn sie im aktuellen Browser nicht verfügbar ist:

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

Beispiel

bind () - PrototypeJS-Dokumentation


Was ist aus Interesse der Unterschied zwischen Array.prototype.slice.call(arguments)und arguments.slice()?
sje397

7
@ sje397: Argumente sind kein * echtes * Array, daher gibt es keine Slice () -Methode. Die Slice () -Methode für Array.prototype ist jedoch absichtlich generisch, sodass Sie jedes Objekt mit numerischen Indizes und einer Längeneigenschaft übergeben können und es funktioniert.
Andy E

2
Dies ist die eleganteste Antwort
Antoine

Diese .bind () ist wirklich großartig und erweitert die Verwendung und Einfachheit von Rückrufen erheblich. Als grundlegendes Beispiel, um es zu verstehen, wenn Sie haben:f = function(arg1,arg2){alert(arg1+arg2);}.bind(this,"abc"); f("def") // Gives "abcdef"
Le Droid

Dies ist wirklich eine gute Antwort. Super und gut für mich arbeiten. Vielen Dank :)
Vishnu Mishra

13

Wenn Sie einen Rückruf haben, der von etwas anderem als Ihrem Code mit einer bestimmten Anzahl von Parametern aufgerufen wird, und Sie zusätzliche Parameter übergeben möchten, können Sie eine Wrapper-Funktion als Rückruf übergeben und innerhalb des Wrappers die zusätzlichen Parameter übergeben.

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
}

9

Wenn Sie nicht sicher sind, wie viele Parameter an Rückruffunktionen übergeben werden sollen, verwenden Sie die applyFunktion.

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

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

callbackTester(tryMe,['hello','goodbye']);

4

Umschließen Sie die übergebenen 'untergeordneten' Funktionen als / mit Argumenten in Funktionsumbrüchen, um zu verhindern, dass sie beim Aufruf der übergeordneten Funktion ausgewertet werden.

function outcome(){
    return false;
}

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

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

4

Code aus einer Frage mit einer beliebigen Anzahl von Parametern und einem Rückrufkontext:

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

2

Verwenden Sie die Curry-Funktion wie in diesem einfachen Beispiel.

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>


0

Eine neue Version für das Szenario, in dem der Rückruf von einer anderen Funktion aufgerufen wird, nicht von Ihrem eigenen Code, und Sie zusätzliche Parameter hinzufügen möchten.

Nehmen wir zum Beispiel an, Sie haben viele verschachtelte Aufrufe mit Erfolgs- und Fehlerrückrufen. Ich werde für dieses Beispiel Winkelversprechen verwenden, aber jeder Javascript-Code mit Rückrufen wäre für diesen Zweck der gleiche.

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

Jetzt möchten Sie möglicherweise Ihren Code übersichtlicher gestalten, indem Sie eine Funktion zum Protokollieren von Fehlern definieren und den Ursprung des Fehlers für Debugging-Zwecke beibehalten. So würden Sie Ihren Code umgestalten:

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

Die aufrufende Funktion fügt den Fehlerparameter nach den Parametern Ihrer Rückruffunktion hinzu.


0

Ich habe nach der gleichen Sache gesucht und am Ende die Lösung gefunden. Hier ist ein einfaches Beispiel, wenn jemand dies durchgehen möchte.

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

Auch auf die andere Frage hier gepostet


0

Lassen Sie mich Ihnen ein sehr einfaches Beispiel für die Verwendung eines Rückrufs im Node.j-Stil geben:

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

und das HTML, das das Ergebnis rendert:

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

Sie können hier damit spielen: https://jsfiddle.net/q8gnvcts/ - versuchen Sie beispielsweise, eine Zeichenfolge anstelle einer Zahl zu übergeben: myTest ('eine Zeichenfolge', 6, Funktion (err, Ergebnis) .. und sehen Sie das Ergebnis.

Ich hoffe, dieses Beispiel hilft, weil es die Grundidee von Rückruffunktionen darstellt.


0
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");

Lesen Sie mehr über die Spread-Syntax


0
//Suppose function not taking any parameter means just add the GetAlterConfirmation(function(result) {});
GetAlterConfirmation('test','messageText',function(result) {
                        alert(result);
    }); //Function into document load or any other click event.


function GetAlterConfirmation(titleText, messageText, _callback){
         bootbox.confirm({
                    title: titleText,
                    message: messageText,
                    buttons: {
                        cancel: {
                            label: '<i class="fa fa-times"></i> Cancel'
                        },
                        confirm: {
                            label: '<i class="fa fa-check"></i> Confirm'
                        }
                    },
                    callback: function (result) {
                        return _callback(result); 
                    }
                });

1
Bitte fügen Sie eine Erklärung hinzu, was Sie tun und warum :)
Preston Badeer

Okay, ich werde von meiner nächsten Antwort an tun, entschuldigen Sie das oben Gesagte, da dies meine erste Antwort ist.
Santhos Jery
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.