jQuery कॉलबैक में अधिक पैरामीटर पास करता है


255

क्या jQuery में कॉलबैक फ़ंक्शन में अधिक डेटा पास करने का एक तरीका है?

मेरे पास दो कार्य हैं और मैं चाहता हूं कि कॉलबैक $.post, उदाहरण के लिए, AJAX कॉल के परिणामी डेटा दोनों को पास करने के लिए, साथ ही साथ कुछ कस्टम तर्क भी।

function clicked() {
    var myDiv = $("#my-div");
    // ERROR: Says data not defined
    $.post("someurl.php",someData,doSomething(data, myDiv),"json"); 
    // ERROR: Would pass in myDiv as curData (wrong)
    $.post("someurl.php",someData,doSomething(data, myDiv),"json"); 
}

function doSomething(curData, curDiv) {

}

मैं एक कॉलबैक में अपने स्वयं के मापदंडों को पारित करने में सक्षम होना चाहता हूं, साथ ही साथ AJAX कॉल से वापस लौटा परिणाम।


14
यह ध्यान देने योग्य है कि jQuery.ajax () में 1.4 के बाद से एक संदर्भ सेटिंग है ( jquery14.com/day-01/jquery-14 ) इसके उपयोग का एक उदाहरण यहां देखें: stackoverflow.com/questions/5097191/ajax-context- विकल्प /…
रुसौ

मैंने AJAX पूरी होने के बाद डेटा को वापस करने में अपनी समस्या बताई और फिर मैं doSomething।
ओनागैग

जवाबों:


340

समाधान क्लोजर के माध्यम से चर का बंधन है।


अधिक बुनियादी उदाहरण के रूप में, यहां एक उदाहरण फ़ंक्शन है जो कॉलबैक फ़ंक्शन को प्राप्त करता है और कॉल करता है, साथ ही एक उदाहरण कॉलबैक फ़ंक्शन:

function callbackReceiver(callback) {
    callback("Hello World");
}

function callback(value1, value2) {
    console.log(value1, value2);
}

यह कॉलबैक कॉल करता है और एकल तर्क की आपूर्ति करता है। अब आप एक अतिरिक्त तर्क देना चाहते हैं, इसलिए आप कॉलबैक को बंद कर देते हैं।

callbackReceiver(callback);     // "Hello World", undefined
callbackReceiver(function(value) {
    callback(value, "Foo Bar"); // "Hello World", "Foo Bar"
});

या, ES6 एरो फ़ंक्शंस का उपयोग करके अधिक :

callbackReceiver(value => callback(value, "Foo Bar")); // "Hello World", "Foo Bar"

आपके विशिष्ट उदाहरण के लिए, मैंने .postjQuery में फ़ंक्शन का उपयोग नहीं किया है , लेकिन दस्तावेज़ का एक त्वरित स्कैन बताता है कि कॉल बैक में निम्नलिखित हस्ताक्षर के साथ एक फ़ंक्शन पॉइंटर होना चाहिए :

function callBack(data, textStatus, jqXHR) {};

इसलिए मुझे लगता है कि समाधान इस प्रकार है:

var doSomething = function(extraStuff) {
    return function(data, textStatus, jqXHR) {
        // do something with extraStuff
    };
};

var clicked = function() {
    var extraStuff = {
        myParam1: 'foo',
        myParam2: 'bar'
    }; // an object / whatever extra params you wish to pass.

    $.post("someurl.php", someData, doSomething(extraStuff), "json");
};

क्या हो रहा है?

अंतिम पंक्ति में, doSomething(extraStuff)है लाया और कहा कि मंगलाचरण का परिणाम एक है समारोह सूचक

क्योंकि extraStuffयह एक तर्क के रूप में पारित किया doSomethingगया है जो कार्य के दायरे में है doSomething

जब extraStuffयह लौटाया जाता है अनाम आंतरिक कार्य के संदर्भ में doSomethingबाहरी फ़ंक्शन के extraStuffतर्क को बंद करके बाध्य है । doSomethingवापस आने के बाद भी यह सच है ।

मैंने उपरोक्त परीक्षण नहीं किया है, लेकिन मैंने पिछले 24 घंटों में बहुत समान कोड लिखा है और जैसा मैंने बताया है, यह काम करता है।

आप निश्चित रूप से अपनी व्यक्तिगत पसंद / कोडिंग मानकों के आधार पर एक 'एक्स्ट्रास्टफ' ऑब्जेक्ट के बजाय कई चर पास कर सकते हैं।


'Var doSomething =' का उद्देश्य क्या है? यह केवल एक कार्य के रूप में घोषित करने से अलग है (यानी फ़ंक्शन doSomething (...) {})
डेव

7
यह सच नहीं है। इन दो फ़ंक्शन घोषणाओं पर अलग-अलग गुंजाइश नियम लागू होते हैं। जेएस रनटाइम (ब्राउज़र पढ़ें) के आधार पर व्यवहार बहुत भिन्न होता है। फायरबग में स्टैकट्रेस / ब्रेकपॉइंट में दिखाए गए फ़ंक्शन नाम की तुलना करने का प्रयास करें।
इहर कहार्लिचेंको

1
Ihor: आप दो घोषणा शैलियों के बीच अंतर के बारे में बिल्कुल सही हैं। एक अच्छी व्याख्या यहाँ है: stackoverflow.com/questions/336859/…
ब्रैडहाउस

2
उदाहरण की विशिष्टता के कारण इसे अधिक सामान्य समस्याओं पर लागू करने का प्रयास करने वाले उपयोगकर्ताओं के लिए अनुसरण करना थोड़ा मुश्किल हो सकता है। मैंने एक सरलीकृत उदाहरण जोड़ दिया है, इसे पालन करना थोड़ा आसान है, साथ ही एक तीर फ़ंक्शन उदाहरण है ताकि इस प्रश्न को नए पोस्ट प्रस्तावित डुप्लिकेट के डुप्लिकेट के रूप में बंद किया जा सके। यदि आपको लगता है कि मेरे संपादन आपके उत्तर के मूल इरादे से बहुत दूर हैं, या किसी अन्य तरीके से अनुपयुक्त हैं, तो कृपया इसे वापस लेने के लिए स्वतंत्र महसूस करें।

4
इस उत्तर के संशोधन 4 में मेटा
bjb568

82

उपयोग करते समय doSomething(data, myDiv), आप वास्तव में फ़ंक्शन को कॉल करते हैं और इसके लिए संदर्भ नहीं बनाते हैं।

आप या तो doStomethingफ़ंक्शन को सीधे पास कर सकते हैं लेकिन आपको यह सुनिश्चित करना होगा कि इसमें सही हस्ताक्षर हैं।

यदि आप doSomething जिस तरह से है रखना चाहते हैं, तो आप एक अनाम फ़ंक्शन में इसकी कॉल को लपेट सकते हैं।

function clicked() {
    var myDiv = $("#my-div");
    $.post("someurl.php",someData, function(data){ 
      doSomething(data, myDiv)
    },"json"); 
}

function doSomething(curData, curDiv) {
    ...
}

अनाम फ़ंक्शन कोड के अंदर, आप एन्कोडिंग क्षेत्र में परिभाषित चर का उपयोग कर सकते हैं। यह एक तरह से जावास्क्रिप्ट स्कूपिंग का काम करता है।


9
स्पष्टता के लिए यह सबसे अच्छा समाधान आईएमओ है। return function(...){...}फ़ंक्शन के भीतर कोई अतिरिक्त फ़ंक्शन नहीं doSomething। मुझे यहाँ उसी अवधारणा का एक और स्पष्ट उदाहरण मिला: theelitist.net/…
विलियम डेनिस

4
मुझे लगता है कि यह एक समस्या है। यदि आपका अतिरिक्त डेटा (इस मामले में myDiv) कॉलबैक की आग से पहले बदल जाता है, तो आपको नया मूल्य मिलता है और पुराना नहीं! मेरे मामले में, मैं एक सरणी में आइटम पर अजाक्स कॉल को बंद कर रहा था, और जब तक पहली सफलता () कॉल निष्पादित हुई, तब तक यह सोचा था कि यह आखिरी आइटम पर सफल हुआ था जब यह पहली बार था! ब्रैडहाउस के जवाब ने मेरे लिए काम किया।
क्रिस

@ क्रिस हां, कैद किए गए चर जावास्क्रिप्ट में बदले जा सकते हैं। यदि आप इस व्यवहार को नहीं चाहते हैं, तो आपको मूल्य पर कब्जा करने के लिए एक स्पष्ट फ़ंक्शन बनाने की आवश्यकता है। सबसे सामान्य मुहावरा (function(myDiv){ ... })(myDiv)चर को पकड़ने के लिए एक स्व निष्पादित कार्य है myDiv। यह स्पष्ट रूप से @ ब्रैडहाउस उत्तर में किया गया है।
विंसेंट रॉबर्ट

यदि आप इस ajax n बार कॉल करते हैं, तो यह विधि अलग-अलग फ़ंक्शन बनाती है और उन्हें सफलता कॉलबैक में भेजती है। यह perfonmance के मामले में बुरा है। इस @zeroasterisk का जवाब देने के लिए अच्छा है।
यिलामज़

मैं @WilliamDenniss से सहमत हूं, IMHO यह सबसे अच्छा, सरल और स्पष्ट समाधान है
sebasira

52

यह वास्तव में हर किसी के लिए ध्वनि बनाने से आसान है ... खासकर यदि आप $.ajax({})आधार सिंटैक्स बनाम सहायक कार्यों में से एक का उपयोग करते हैं ।

बस key: valueजोड़ी में पास करें जैसे आप किसी भी वस्तु पर होंगे, जब आप अपने ajax अनुरोध को सेटअप करते हैं ... (क्योंकि $(this)अभी तक संदर्भ नहीं बदला है, यह अभी भी ऊपर कॉल बाइंड के लिए ट्रिगर है)

<script type="text/javascript">
$(".qty input").bind("keypress change", function() {
    $.ajax({
        url: "/order_items/change/"+$(this).attr("data-order-item-id")+"/qty:"+$(this).val()+"/returnas.json",
        type: "POST",
        dataType: "json",
        qty_input: $(this),
        anything_else_i_want_to_pass_in: "foo",
        success: function(json_data, textStatus, jqXHR) {
            /* here is the input, which triggered this AJAX request */
            console.log(this.qty_input);
            /* here is any other parameter you set when initializing the ajax method */
            console.log(this.anything_else_i_want_to_pass_in);
        }
    });
});
</script>

इसका एक कारण यह है कि var को सेट करने से बेहतर है, यह है कि var ग्लोबल है और जैसे कि, overwritable ... यदि आपके पास 2 चीजें हैं जो ajax कॉल्स को ट्रिगर कर सकती हैं, तो आप सिद्धांत रूप में उन्हें ajax कॉल रिस्पॉन्स से तेजी से ट्रिगर कर सकते हैं, और आपके पास पहले में पारित दूसरी कॉल के लिए मूल्य होगा। इस विधि का उपयोग करते हुए, ऊपर, ऐसा नहीं होगा (और इसका उपयोग करना बहुत सरल है)।


3
यही वह है जिसकी तलाश में मैं हूं। मुझे नहीं पता था कि जब आप डेटा टाइप को निर्दिष्ट करते हैं तो json के रूप में यह आपके लिए प्रतिक्रिया को स्वचालित रूप से पार्स कर देता है। वह अच्छा: (:
मुर्गा

1
मेरे लिए कॉलबैक में अतिरिक्त पैरामेट्स पास करने का सबसे अच्छा तरीका लगता है। मुझे दिलचस्पी होगी अगर कोई भी इस दृष्टिकोण के साथ एक खामी देखता है? सबसे आसान और सबसे सुंदर। धन्यवाद!
Jan Zyka

" संस्करण वैश्विक है और इस तरह, अधिलेखित है "। यह नहीं है यदि आप इसे एक फ़ंक्शन के भीतर घोषित करते हैं, जो ऊपर दिए गए समाधान की तुलना में बहुत अधिक पठनीय है। क्लोजर का उपयोग करना एक क्लीनर दृष्टिकोण है - यहां मेरा जवाब देखें: stackoverflow.com/a/18570951/885464
लोरेंजो पोलिडोरी

5
@ लॉरेंजोपोलोरी मैं असहमत हूं, मुझे लगता है कि अतिरिक्त पैरामीटर दृष्टिकोण कहीं अधिक पठनीय है।
एंड्रयू प्लमर

2
यह बिल्कुल शानदार है। कैसे आया यह मैंने पहले कभी नहीं देखा। मुझे इसकी आवश्यकता नहीं है कि closureमुझे काम करने की आवश्यकता है और यह पूरी तरह से इक्का, स्वच्छ, सरल और गैर वैश्विक है।
पायोतर कुला

21

आज की दुनिया में एक और उत्तर है जो क्लीनर है, और एक और स्टैक ओवरफ्लो उत्तर से लिया गया है:

function clicked()
{
    var myDiv = $( "#my-div" );

    $.post( "someurl.php", {"someData": someData}, $.proxy(doSomething, myDiv), "json" );
}

function doSomething( data )
{
    // this will be equal to myDiv now. Thanks to jQuery.proxy().
    var $myDiv = this;

    // doing stuff.
    ...
}

यहाँ मूल प्रश्न और उत्तर है: jQuery कैसे? $ .ajax कॉल के लिए सफलता कॉलबैक के लिए अतिरिक्त पैरामीटर पास करें?


8

आप निम्न की तरह कुछ भी आज़मा सकते हैं:

function clicked() {

    var myDiv = $("#my-div");

    $.post("someurl.php",someData,function(data){
        doSomething(data, myDiv);
    },"json"); 
}

function doSomething(curData, curDiv) {

}

5

आप जावास्क्रिप्ट का उपयोग बंद कर सकते हैं:

function wrapper( var1, var2,....) // put here your variables
{
  return function( data, status)
  {
     //Handle here results of call
  }
};

और जब आप कर सकते हैं:

$.post("someurl.php",data,wrapper(var1, var2, etc...),"html");

3

मैंने अपनी पिछली पोस्ट में एक गलती की है। कॉलबैक फ़ंक्शन में अतिरिक्त तर्क कैसे पास करें, इसके लिए यह उदाहरण काम कर रहा है:

function custom_func(p1,p2) {
    $.post(AJAX_FILE_PATH,{op:'dosomething',p1:p1},
        function(data){
            return function(){
                alert(data);
                alert(p2);
            }(data,p2)
        }
    );
    return false;
}

1
आपको अपना मूल उत्तर संपादित करना चाहिए, या नया जोड़ने से पहले इसे हटा देना चाहिए।
ब्लेज़ेमॉन्गर

3

चलो सरल जाओ! :)

$.ajax({
    url: myUrl,
    context: $this, // $this == Current $element
    success: function(data) {
        $.proxy(publicMethods.update, this)(data); // this == Current $element
    }
});

2

.ajax()JQuery एपीआई का उपयोग करके अतुल्यकालिक अनुरोध भेजने और कॉलबैक फ़ंक्शन के लिए अतिरिक्त पैरामीटर पास करने के लिए एक अधिक सामान्य समाधान :

function sendRequest(method, url, content, callback) {
    // additional data for the callback
    var request = {
        method: method,
        url: url
    };

    $.ajax({
        type: method,
        url: url,
        data: content
     }).done(function(data, status, xhr) {
        if (callback) callback(xhr.status, data, request);
     }).fail(function(xhr, status) {
        if (callback) callback(xhr.status, xhr.response, request);
     });
};

1

मेरे लिए, और अन्य नए शौक जिन्होंने अभी-अभी जावास्क्रिप्ट के साथ संपर्क किया है,
मुझे लगता है कि यह Closeure Solutionथोड़ा भ्रमित करने वाला है।

जबकि मैंने पाया कि, आप आसानी से जितने भी अजाक्स कॉलबैक का उपयोग करना चाहते हैं उतने मापदंडों को पास कर सकते हैं।

यहां दो आसान उपाय दिए गए हैं ।

पहले एक, जो @ एज़ोस्टरस्क ने ऊपर उल्लेख किया है, उदाहरण:

var $items = $('.some_class');
$.each($items, function(key, item){
    var url = 'http://request_with_params' + $(item).html();
    $.ajax({
        selfDom     : $(item),
        selfData    : 'here is my self defined data',

        url         : url,
        dataType    : 'json',
        success     : function(data, code, jqXHR){
            // in $.ajax callbacks, 
            // [this] keyword references to the options you gived to $.ajax
            // if you had not specified the context of $.ajax callbacks.
            // see http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings context
            var $item = this.selfDom;
            var selfdata = this.selfData;
            $item.html( selfdata );
            ...
        } 
    });
});

दूसरा, उन्हें स्वयं-परिभाषित-डेटा पास करके, XHR object जिसमें पूरे अजाक्स-अनुरोध-प्रतिक्रिया जीवन काल में मौजूद है।

var $items = $('.some_class');
$.each($items, function(key, item){
    var url = 'http://request_with_params' + $(item).html();
    $.ajax({
        url         : url,
        dataType    : 'json',
        beforeSend  : function(XHR) {
            // 为了便于回调,把当前的 jquery对象集存入本次 XHR
            XHR.selfDom = $(item);
            XHR.selfData = 'here is my self defined data';
        },
        success     : function(data, code, jqXHR){
            // jqXHR is a superset of the browser's native XHR object
            var $item = jqXHR.selfDom;
            var selfdata = jqXHR.selfData;
            $item.html( selfdata );
            ...
        } 
    });
});

जैसा कि आप देख सकते हैं कि इन दो समाधानों में एक खामी है: आपको हर बार लिखने की तुलना में हर बार थोड़ा और कोड लिखना होगा:

$.get/post (url, data, successHandler);

$ .Ajax के बारे में अधिक पढ़ें: http://api.jquery.com/jquery.ajax/


1

अगर कोई अभी भी यहाँ आता है, तो यह मेरा लेना है:

$('.selector').click(myCallbackFunction.bind({var1: 'hello', var2: 'world'}));

function myCallbackFunction(event) {
    var passedArg1 = this.var1,
        passedArg2 = this.var2
}

यहां क्या होता है, कॉलबैक फ़ंक्शन के लिए बाध्य होने के बाद, यह फ़ंक्शन के भीतर उपलब्ध होगा this

यह विचार कैसे रिएक्ट bindकार्यक्षमता का उपयोग करता है से आता है ।


1
$(document).on('click','[action=register]',function(){
    registerSocket(registerJSON(),registerDone,second($(this)));
});

function registerSocket(dataFn,doneFn,second){
                 $.ajax({
                       type:'POST',
                       url: "http://localhost:8080/store/public/register",
                       contentType: "application/json; charset=utf-8",
                       dataType: "json",
                       data:dataFn
                 }).done ([doneFn,second])
                   .fail(function(err){
                            console.log("AJAX failed: " + JSON.stringify(err, null, 2));
                        });
}

function registerDone(data){
    console.log(JSON.stringify(data));
}
function second(element){
    console.log(element);
}

दूसरा तरीका:

function socketWithParam(url,dataFn,doneFn,param){
  $.ajax({
    type:'POST',
    url:url,
    contentType: "application/json; charset=utf-8",
    headers: { 'Authorization': 'Bearer '+localStorage.getItem('jwt')},
    data:dataFn
    }).done(function(data){
      doneFn(data,param);
    })
    .fail(function(err,status,xhr){
    console.log("AJAX failed: " + JSON.stringify(err, null, 2));
    });
}

$(document).on('click','[order-btn]',function(){
  socketWithParam(url,fakeDataFn(),orderDetailDone,secondParam);
});

function orderDetailDone(data,param){
  -- to do something --
}

0

वास्तव में, जब आप लिखते हैं तो आपका कोड काम नहीं कर रहा है:

$.post("someurl.php",someData,doSomething(data, myDiv),"json"); 

आप फ़ंक्शन संदर्भ के बजाय तीसरे कॉल के रूप में एक फ़ंक्शन कॉल करते हैं ।


0

B01 के उत्तर के परिशिष्ट के रूप में , का दूसरा तर्क $.proxyअक्सर thisसंदर्भ को संरक्षित करने के लिए उपयोग किया जाता है । अतिरिक्त तर्कों $.proxyको आंशिक रूप से फ़ंक्शन पर लागू किया जाता है, इसे डेटा के साथ पूर्व-भरना। ध्यान दें कि $.postकॉलबैक के लिए कोई भी तर्क अंत में लागू किया जाएगा, इसलिए doSomethingइसके तर्क सूची के अंत में होना चाहिए:

function clicked() {
    var myDiv = $("#my-div");
    var callback = $.proxy(doSomething, this, myDiv);
    $.post("someurl.php",someData,callback,"json"); 
}

function doSomething(curDiv, curData) {
    //"this" still refers to the same "this" as clicked()
    var serverResponse = curData;
}

यह दृष्टिकोण कॉलबैक के लिए कई तर्कों को बाध्य करने की अनुमति देता है:

function clicked() {
    var myDiv = $("#my-div");
    var mySpan = $("#my-span");
    var isActive = true;
    var callback = $.proxy(doSomething, this, myDiv, mySpan, isActive);
    $.post("someurl.php",someData,callback,"json"); 
}

function doSomething(curDiv, curSpan, curIsActive, curData) {
    //"this" still refers to the same "this" as clicked()
    var serverResponse = curData;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.