JavaScript: Parametreleri geri arama işlevine aktarma


289

Geri arama olarak kullanılan bir işleve bazı parametreler geçirmeye çalışıyorum, bunu nasıl yapabilirim?

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

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

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

9
Yaptığın şey işe yaramalı. Ne gibi problemlerin var?
Daniel Vassallo

1
Kodunuz iyi çalışıyor, sorun nedir?
Sarfraz

1
Çalışmalı ... jsfiddle.net/QXQZj
Hristo

ne yazık ki bu ana kod sözdizimdeki benim hatamdı, çünkü bu JavaScript'te bir geri arama ilk kez kullandığımı düşündüm
vitto

Bir geri aramaya parametre eklemek istiyorsanız, ancak onu çağıran şeyi değiştiremiyorsanız (argüman sırasını değiştirme gücünüz olmadığı için, JS bind ile bazı geri arama parametrelerini önceden bağladığım gibi, bu cevap: stackoverflow.com/a/28120741/1695680
ThorSummoner

Yanıtlar:


253

Biraz daha genel bir şey istiyorsanız, arguments değişkenini şöyle kullanabilirsiniz:

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

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

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

Ancak aksi halde, örneğin iyi çalışır (test cihazında geri arama yerine [0] bağımsız değişkenleri kullanılabilir)


53
Genel olma ruhunda olduğumuz sürece callback.apply(arguments), işlev gövdesi callbackTesteriki argüman senaryosunun ötesine genişletilebilir.
Steven

1
Üzgünüz, ana kodda bir sözdizimi hatasıydı, bu olduğunu düşündüm çünkü bu JavaScript'te ilk kez bir geri arama kullanıyorum, bunun probelm olmadığını anlamama ve harika bir örnek görmeme yardımcı oldunuz.
vitto

3
Anonim bir işlev (Marimuthu'nun yanıtı) veya .bind () (Andy'nin yanıtı) kullanarak FYI, bağımsız değişkenleri geri aramaya iletmenin çok daha temiz yoludur.
antoine

203

Bu da işe yarar:

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

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

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

Başka Bir Senaryo:

// 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
Bu harika çalışır çünkü anonim işlevin şöyle parametreler geçirmesine izin verir: callbackTester (function (data) {tryMe (data, "merhaba", "güle güle");});
Michael Khalili

Ayrıca geri aramanın aslında bir işlev olup olmadığını kontrol etmek istiyorum. if (typeof window[callback] == 'function') window[callback].call(this);
GreeKatrina

63

Sorunuz belirsiz. Bunu daha basit bir şekilde nasıl yapabileceğinizi soruyorsanız , Function.prototype üyesi olan ECMAScript 5. baskı yöntemine .bind () bir göz atmalısınız . Bunu kullanarak, böyle bir şey yapabilirsiniz:

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

function callbackTester (callback) {
    callback();
}

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

Geçerli tarayıcıda yoksa yöntemi ekleyen şu kodu da kullanabilirsiniz:

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

Misal

bind () - PrototyJJ Belgeleri


İlgi dışı Array.prototype.slice.call(arguments)ve arasındaki fark arguments.slice()nedir?
sje397

7
@ sje397: arguments bir * real * dizisi değildir, dolayısıyla slice () yöntemi yoktur. Ancak, Array.prototype üzerindeki slice () yöntemi kasıtlı olarak geneldir, bu nedenle sayısal dizinler ve length özelliği olan herhangi bir nesneyi iletebilirsiniz ve çalışır.
Andy E

2
Bu en şık cevap
antoine

Bu .bind () gerçekten harika ve geri aramaların kullanımı ve basitliğini çok genişletiyor. Bunu anlamak için temel bir örnek olarak, eğer varsa:f = function(arg1,arg2){alert(arg1+arg2);}.bind(this,"abc"); f("def") // Gives "abcdef"
Le Droid

Bu gerçekten bir cevap. Harika ve benim için iyi çalışıyor. Teşekkür ederim :)
Vishnu Mishra

13

Belirli sayıda parametre ile kodunuzdan başka bir şey tarafından çağrılacak bir geri çağrınız olduğunda ve ek parametrelerde geçmek istediğinizde, geri arama ve sargıcının içinde ek parametreler geçtikçe bir sarıcı işlevini geçebilirsiniz.

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

Geri arama işlevlerine kaç parametrenin aktarılacağından emin değilseniz, işlevi kullanın apply.

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

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

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

4

'Parent' işlevi çağrıldığında bunların değerlendirilmesini önlemek için işlev sarmalayıcıları içinde / ile argümanlar olarak iletilen 'child' işlev (ler) i sarın.

function outcome(){
    return false;
}

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

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

4

Herhangi bir sayıda parametreye ve geri arama içeriğine sahip bir sorudan kod:

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

Bu basit örnekte olduğu gibi curried işlevini kullanın.

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

Geri arama işleminin kendi kodunuz tarafından değil başka bir işlev tarafından çağrılacağı ve ek parametreler eklemek istediğiniz senaryo için yeni bir sürüm.

Örneğin, başarılı ve hata geri aramaları olan çok sayıda iç içe çağrınız olduğunu varsayalım. Bu örnek için açısal vaatler kullanacağım, ancak geri çağrıları olan herhangi bir javascript kodu bu amaç için aynı olacaktır.

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

Artık hata ayıklama amacıyla hatanın kaynağını koruyarak hataları günlüğe kaydetmek için bir işlev tanımlayarak kodunuzu karmaşık hale getirmek isteyebilirsiniz. Kodunuzu yeniden düzenlemeye şu şekilde devam edersiniz:

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

Arama işlevi, geri arama işlevi parametrelerinizden sonra hala hata parametresini ekleyecektir.


0

Ben de aynı şeyi arıyordum ve sonuçta çözüm buldum ve burada kimse bunu yapmak istiyorsa basit bir örnek.

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

Ayrıca diğer soru üzerine yayınlanmıştır burada


0

Size geri arama kullanma konusunda çok sade bir Node.js stili örneği vereyim:

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

ve sonucu verecek HTML:

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

Burada onunla oynayabilirsiniz: https://jsfiddle.net/q8gnvcts/ - örneğin sayı yerine dize geçirmeye çalışın: myTest ('bazı dize', 6, işlev (err, sonuç) .. ve sonucu görün.

Umarım bu örnek yardımcı olur, çünkü geri arama işlevleri hakkında temel fikri temsil eder.


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

forma sözdizimi hakkında daha fazla bilgi


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
Lütfen ne yaptığınıza ve neden yaptığınıza dair bir açıklama ekleyin :)
Preston Badeer

Tamam, bir sonraki cevabımdan yapacağım, yukarıdakiler için üzgünüm çünkü bu benim ilk cevabım.
Santhos Jery
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.