jQueryがコールバックに追加のパラメーターを渡す


255

jQueryのコールバック関数にさらにデータを渡す方法はありますか?

2つの関数があり$.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-オプション/…
russau

AJAXの完了後にデータを返す際の問題を解決した後、何かを行いました。
Onaiggac

回答:


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"

特定の例については.post、jQueryで関数を使用していませんが、ドキュメントを簡単にスキャンすると、コールバックは次のシグネチャを持つ関数ポインターであることが示唆されています。

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時間に非常によく似たコードを記述しました。

もちろん、個人の好み/コーディング標準に応じて、単一の「extraStuff」オブジェクトの代わりに複数の変数を渡すことができます。


'var doSomething ='の目的は何ですか?これは、doSomethingを関数として宣言すること(つまり、関数doSomething(...){})とどのように異なるのですか
Dave Neeley

7
それは真実ではない。これらの2つの関数宣言には、異なるスコープルールが適用されます。JSランタイム(読み取りブラウザー)によって動作が大きく異なります。また、Firebugのスタックトレース/ブレークポイントに表示される関数名を比較してみてください。
Ihor Kaharlichenko '25年

1
Ihor:あなたは2つの宣言スタイルの違いについて完全に正しいです。良い説明はこちらです:stackoverflow.com/questions/336859/…–
bradhouse

2
例の特異性のため、これをより一般的な問題に適用しようとするユーザーにとって、これは少し難しいかもしれません。わかりやすくするための簡単な例と、新しく投稿された提案された複製の複製としてこの質問が閉じられないようにする矢印関数の例を追加しました。私の編集が元の回答の意図から離れすぎていると感じた場合、またはその他の点で不適切であると感じた場合は、遠慮なくロールバックしてください。

4
この回答のリビジョン4はメタ
bjb568 '27

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) {
    ...
}

無名関数コード内では、囲みスコープで定義された変数を使用できます。これは、JavaScriptスコーピングが機能する方法です。


9
これは、明確にするためにIMOの最良のソリューションです。return function(...){...}関数内に追加の関数はありませんdoSomething。:私はここに同じ概念の別の明確な例見つかっtheelitist.net/...
ウィリアムDenniss

4
これには問題があると思います。コールバックが発生する前に追加データ(この場合はmyDiv)が変更されると、古い値ではなく新しい値が取得されます。私の場合、私は配列内の項目に対してajax呼び出しを開始していました。最初のsuccess()呼び出しが実行されるまでに、最初のときに最後の項目で成功したと思っていました。ブラッドハウスの答えは私のために働いた。
Chris

@Chrisはい、取得した変数はJavaScriptで変更できます。この動作を望まない場合は、値を取得する明示的な関数を作成する必要があります。最も一般的なイディオムは(function(myDiv){ ... })(myDiv)、変数を取得する自己実行関数ですmyDiv。これは暗黙的に@bradhouseの回答で行われます。
Vincent Robert

このajaxをn回呼び出すと、このメソッドはn個の異なる関数を作成し、それらを成功コールバックに渡します。これはパフォーマンスの点で悪いです。この@zeroasteriskの回答を控えるのは良いことです。
ユルマズ

私は@WilliamDennissに同意します。私見はこれが最良のシンプルで明確な解決策です
sebasira

52

それは実際に誰もが音を出すよりも簡単です...特に$.ajax({})基本構文とヘルパー関数の1つを使用する場合。

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を設定するよりも優れている理由の1つは、varがグローバルであるため、上書き可能であることです... ajax呼び出しをトリガーできるものが2つある場合、理論的にはajax呼び出しが応答するよりも速くトリガーできます。 2番目の呼び出しの値が最初の呼び出しに渡されます。上記のこの方法を使用すると、それは起こりません(使用するのも非常に簡単です)。


3
これはまさに私が探していたものです。dataTypeをjsonとして指定すると、応答が自動的に解析されたことがわかりませんでした。いいですね(:
オンドリ

1
追加のパラメーターをコールバックに渡す最良の方法のように思えます。誰かがこのアプローチの欠点を見つけたら私は興味がありますか?最も簡単で最もエレガント。ありがとう!
Jan Zyka 2013

varはグローバルであるため、上書き可能です。」関数内で宣言するのではなく、上記の解決策よりもはるかに読みやすいです。クロージャーの使用はよりクリーンなアプローチです-私の回答をここで参照してください:stackoverflow.com/a/18570951/885464
Lorenzo Polidori

5
@LorenzoPolidori同意しません。追加のパラメータアプローチははるかに読みやすいと思います。
Andrew Plummer、

2
これは絶対に素晴らしいです。どうしてこれまで見たことがないのですか。私はそれが機能するのclosureに必要なだけではなく、これは完全にエースでクリーンでシンプルでグローバルではありません。
Piotr Kula

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

元の質問と答えは次のとおりです 。jQueryHOW TO ?? $ .ajax呼び出しの成功コールバックに追加のパラメーターを渡しますか?


8

次のようなことも試すことができます。

function clicked() {

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

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

function doSomething(curData, curDiv) {

}

5

JavaScriptのクロージャーを使用できます。

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
元の回答を編集するか、削除してから新しい回答を追加してください。
Blazemonger、2011年

3

簡単に行こう!:)

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

2

.ajax()jQuery APIとクロージャーを使用して非同期リクエストを送信し、追加のパラメーターをコールバック関数に渡すためのより一般的なソリューション:

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

私や、JavaScriptに触れたばかりの初心者にとって、
これCloseure Solutionは少し混乱しすぎていると思います。

私はそれを見つけましたが、jqueryを使用してすべてのajaxコールバックに必要なだけ多くのパラメーターを簡単に渡すことができます。

ここに2つの簡単な解決策があります。

@zeroasteriskが前述した最初の例、例:

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

2つ目は、自己定義データをXHR object ajax-request-responseの有効期間全体に存在するに追加して渡します。

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

ご覧のとおり、これらの2つのソリューションには欠点があります。次のように書くだけでなく、毎回少し多くのコードを書く必要があります。

$.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

このアイデアは、Reactが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"); 

関数参照ではなく、3番目のパラメーターとして関数呼び出しを配置します


0

b01の回答の補遺として、の2番目の引数は$.proxythis参照を保持するためによく使用されます。に渡される追加の引数は、$.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;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.