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- 옵션 /…
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"

귀하의 특정 예에 관해서는, .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 시간 동안 매우 유사한 코드를 작성했으며 설명한대로 작동합니다.

물론 개인 취향 / 코딩 표준에 따라 단일 'extraStuff'객체 대신 여러 변수를 전달할 수 있습니다.


'var doSomething ='의 목적은 무엇입니까? 어떻게 그냥 함수로 (즉, 기능 해봐요 (...) {}) 해봐요 선언에서이 다르다
데이브 닐리

7
그건 사실이 아니야. 이 두 함수 선언에는 다른 범위 규칙이 적용됩니다. JS 런타임 (읽기 브라우저)에 따라 동작이 많이 다릅니다. 또한 Firebug의 stacktrace / breakpoint에 표시된 함수 이름을 비교하십시오.
Ihor Kaharlichenko

1
Ihor : 두 선언 스타일의 차이점에 대해 완전히 맞습니다. 좋은 설명은 여기에 있습니다 : stackoverflow.com/questions/336859/...
bradhouse

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
이것은 명확성을 위해 최고의 솔루션 IMO입니다. return function(...){...}함수 내에 추가 기능이 없습니다 doSomething. 여기 동일한 개념의 또 다른 좋은 예를 발견 theelitist.net/...는
윌리엄 Denniss에게

4
나는 이것에 문제가 있다고 생각한다. 콜백이 발생하기 전에 추가 데이터 (이 경우 myDiv)가 변경되면 이전 값이 아닌 새로운 값을 얻습니다! 필자의 경우 배열의 항목에 대한 아약스 호출을 시작했으며 첫 번째 success () 호출이 실행될 때 마지막 항목에서 처음 성공했을 때 성공했다고 생각했습니다! bradhouse의 대답이 나를 위해 일했습니다.
Chris

@Chris 예, 캡처 한 변수는 Javascript에서 변경할 수 있습니다. 이 동작을 원하지 않으면 값을 캡처하는 명시 적 함수를 작성해야합니다. 가장 일반적인 관용구는 (function(myDiv){ ... })(myDiv)변수를 캡처 하는 자체 실행 기능 myDiv입니다. 이것은 @bradhouse 답변에서 암시 적으로 수행됩니다.
Vincent Robert

이 ajax를 n 번 호출하면이 메소드는 n 개의 다른 함수를 작성하여 성공 콜백에 전달합니다. 이것은 성능 측면에서 나쁩니다. 이 @zeroasterisk의 대답을 삼가는 것이 좋습니다.
yılmaz

@WilliamDenniss에 동의합니다. IMHO 이것이 가장 간단하고 명확한 해결책입니다
sebasira

52

실제로 모든 사람이 소리를내는 것보다 쉽습니다. 특히 $.ajax({})기본 구문과 도우미 함수 중 하나 를 사용하는 경우 특히 그렇습니다 .

key: value아약스 요청을 설정할 때 어떤 객체에서와 같이 쌍을 전달 하면됩니다 ( $(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가 전역 적이며 덮어 쓸 수 있기 때문입니다 ... 아약스 호출을 트리거 할 수있는 두 가지가 있다면 이론적으로 ajax 호출 응답보다 빠르게 트리거 할 수 있습니다. 두 번째 통화의 값이 첫 번째 통화로 전달됩니다. 위의이 방법을 사용하면 발생하지 않습니다 (사용하기도 매우 간단합니다).


3
이것이 바로 내가 찾던 것입니다. dataType을 json으로 지정했을 때 자동으로 응답을 구문 분석했습니다. 멋지다 (:
Rooster

1
콜백을 위해 추가 매개 변수를 전달하는 가장 좋은 방법 인 것 같습니다. 누군가이 접근법으로 단점을 발견하면 관심이 있습니까? 가장 쉽고 가장 우아합니다. 감사!
Jan Zyka

" var는 전역 적이므로 덮어 쓸 수 있습니다 ". 함수 내에서 선언하면 위의 솔루션보다 훨씬 더 읽기 쉽습니다. 사용 클로저를 깨끗한 방법입니다 - 여기 내 대답을 참조하십시오 stackoverflow.com/a/18570951/885464
로렌조 Polidori

5
@LorenzoPolidori 동의하지 않습니다. 추가 매개 변수 접근 방식이 훨씬 더 읽기 쉽습니다.
앤드류 플러머

2
이것은 절대적으로 훌륭합니다. 내가 이걸 본 적이 없는데 나는 closure그것이 작동하기 위해 필요로 할 필요가 없으며 이것은 절대적으로 에이스, 깨끗하고 단순하며 비전 역적입니다.
Piotr Kula 2016 년

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 HOW 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

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

나, 그냥 자바 스크립트와 접촉 한 다른 초보자의 경우,
나는이 생각 Closeure Solution이 너무 혼란의 작은 종류이다.

내가 찾은 동안 jquery를 사용하여 모든 ajax 콜백에 원하는만큼 많은 매개 변수를 전달할 수 있습니다.

다음은 더 쉬운 두 가지 솔루션 입니다.

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

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

보시다시피이 두 솔루션에는 다음과 같은 단점이 있습니다. 작성하는 것보다 조금 더 많은 코드를 작성해야합니다.

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

함수 참조 대신 함수 호출 을 세 번째 매개 변수로 배치합니다 .


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;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.